alexandrite 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: e1d0a59468bf1b22e33d17848c07d9af25172aadbc78723fbf014d42021bcd55
4
+ data.tar.gz: ffb2f6b45788d233ebb91b601f1ea256ba21b54da4bad154e548f4e20bb9f59b
5
+ SHA512:
6
+ metadata.gz: a706821501297809cad6e2c88c917ae8ea4fd276b5d9fde402b0fddf3aeac0094fdc13f42ac48edd551e397f0b7d34cadab6f3aed3ffa1c21abd1b8c02f7526c
7
+ data.tar.gz: f448f181f9980721ef93df28392ffcd8210687033c8257b470cde53693b07c63015f14807a15a70ce649f45789034c2d10fb3e306e007e96d9f083b77dd6d64e
data/.gitignore ADDED
@@ -0,0 +1,24 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
23
+ .idea
24
+ .rvmrc
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ # Specify your gem's dependencies in alexandrite_base.gemspec
6
+ gemspec
7
+
8
+ gem 'faraday'
9
+ gem 'faraday-decode_xml'
10
+ gem 'rubocop'
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2022 Juan Paulo Pérez-Tejada
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,115 @@
1
+ # gisbn GEM [![Build Status](https://travis-ci.org/eftakhairul/gisbn.svg?branch=master)](https://travis-ci.org/eftakhairul/gisbn) [![GitHub issues](https://img.shields.io/github/issues/eftakhairul/gisbn.svg)](https://github.com/eftakhairul/gisbn/issues) [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/eftakhairul/gisbn/master/LICENSE.txt)
2
+
3
+ It fetches book's information by ISBN number based on Google Book API.
4
+
5
+ - Easy to get all information by ISBN
6
+ - Structure data
7
+
8
+ You don't have to call manually Google API with ISBN number. This gem will do everything for you.
9
+
10
+
11
+
12
+ ### Version
13
+ 0.0.1
14
+
15
+
16
+ ### Installation
17
+ Add this line to your application's Gemfile:
18
+
19
+ ```ruby
20
+ gem 'alexandrite'
21
+ ```
22
+
23
+ And then execute:
24
+
25
+ ```sh
26
+ $ bundle
27
+ ```
28
+
29
+ Or install it yourself as globally:
30
+
31
+ ```sh
32
+ gem install alexandrite
33
+ ```
34
+
35
+
36
+ ## Examples
37
+ book = Gisbn::Book.new "0262033844", "AIzaSyDKepjfaVBRcgsnPALw5s2UNyfOk-1FHUU", "ca"
38
+
39
+ book.title
40
+ #=> "Introduction to Algorithms"
41
+
42
+ book.description
43
+ #=> "A new edition of the essential text and professional reference, with substantial newmaterial on such topics as vEB trees, multithreaded algorithms, dynamic programming, and edge-baseflow."
44
+
45
+ book.publisher
46
+ #=> "MIT Press"
47
+
48
+ book.published_date
49
+ #=> <Date: 2001-02-03 ...>
50
+
51
+ book.isbn_10
52
+ #=> 0262033844
53
+
54
+ book.isbn_13
55
+ #=> 9780262033848
56
+
57
+ book.thumbnail
58
+ #=> http://books.google.com/books/content?id=i-bUBQAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api
59
+
60
+ book.preview
61
+ #=> http://books.google.ca/books?id=i-bUBQAAQBAJ&printsec=frontcover&dq=isbn:0262033844&hl=&cd=1&source=gbs_api
62
+
63
+
64
+ book.gisbn.isbn = 9780321573513
65
+ book.fetch.title => "Algorithms"
66
+
67
+
68
+
69
+ ## Methods
70
+ title >> Returns Book's title as string
71
+ description >> Returns the description of book as string
72
+ isbn(isbn_number) >> Set new isbn
73
+ fetch >> Call to Google Book API and process book information on provided ISBN
74
+ authors >> Return authors' name as comma separated as string
75
+ authors_as_array >> Return authors' name as ruby array. If no book is associated with ISBN number,
76
+ then it return empty array
77
+ publisher >> Return publisher name as string
78
+ isbn_10 >> Return 10 digit ISBN numbers as string
79
+ isbn_13 >> Return 13 digit ISBN numbers as string
80
+ categories >> Return category names as comma separated as string
81
+ categories_as_array >> Return category names as ruby array. If no book is associated with ISBN number,
82
+ then it return empty array
83
+ thumbnail_small >> Return the link of small thumnail
84
+ thumbnail >> Return the link of standard thumnail
85
+ preview_link >> Return the link for previewing the book
86
+ page_count >> Return page count as integer
87
+ published_date >> Return the published date as Ruby object
88
+
89
+
90
+ ### Development
91
+
92
+ Want to contribute? Great!
93
+
94
+ 1. Fork it ( https://github.com/eftakhairul/gisbn/fork )
95
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
96
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
97
+ 4. Push to the branch (`git push origin my-new-feature`)
98
+ 5. Create a new Pull Request
99
+
100
+
101
+ Author
102
+ -----------
103
+ [Eftakhairul Islam](https://eftakhairul.com)
104
+
105
+ Contributors
106
+ -----------
107
+ [Matt Seeberger](https://github.com/thebeardedgeek)
108
+
109
+ License
110
+ ----
111
+ MIT
112
+
113
+
114
+
115
+
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ Dir.glob('tasks/**/*.rake').each(&method(:import))
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'lib/alexandrite/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'alexandrite'
7
+ spec.version = Alexandrite::VERSION
8
+ spec.authors = ['J. P. Pérez-Tejada']
9
+ spec.email = ['jpereztejada@apexsystems.com', 'juan@daiuk.com']
10
+ spec.summary = 'Tools for fetching books data from Google and OCLC'
11
+ spec.description = "Alexandrite is a gem that fetches public book's information by different params based
12
+ on Google Book API and OCLC API . Powered by Faraday."
13
+ spec.homepage = 'https://github.com/maclenn77/alexandrite'
14
+ spec.required_ruby_version = Gem::Requirement.new('>= 3.0')
15
+ spec.license = 'MIT'
16
+
17
+ spec.files = `git ls-files -z`.split("\x0")
18
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
+ spec.require_paths = ['lib']
21
+
22
+ spec.add_development_dependency 'bundler', '>= 2.1.0'
23
+ spec.add_development_dependency 'faraday'
24
+ spec.add_development_dependency 'rake'
25
+
26
+ # #dependency for testing automation
27
+ spec.add_development_dependency 'factory_bot'
28
+ spec.add_development_dependency 'pry-byebug'
29
+ spec.add_development_dependency 'rspec'
30
+ spec.add_development_dependency 'rspec-nc'
31
+ spec.add_development_dependency 'vcr'
32
+ spec.add_development_dependency 'webmock'
33
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Alexandrite
4
+ VERSION = '0.0.1'
5
+ end
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'alexandrite_books'
4
+ require_relative 'alexandrite_google'
5
+ require_relative 'alexandrite_oclc'
6
+ require_relative 'error_type/errors'
7
+
8
+ # Main gem methods for creating books from ISBN
9
+ module Alexandrite
10
+ include ErrorType
11
+
12
+ # Get and Process data from Google API
13
+ class Google
14
+ extend Alexandrite::GoogleAPI
15
+
16
+ attr_reader :result
17
+
18
+ def initialize(key, query)
19
+ @result = search_by(key, query)
20
+ end
21
+
22
+ # @return [Alexandrite::Book]
23
+ def self.create_book(isbn)
24
+ volume_info = get_volume_info(isbn)
25
+ Alexandrite::Book.new(volume_info)
26
+ end
27
+ end
28
+
29
+ # Get and Process data from OCLC API
30
+ class OCLC
31
+ extend Alexandrite::OCLCAPI
32
+
33
+ attr_reader :result
34
+
35
+ # return [Alexandrite::OCLC]
36
+ def initialize(key, query, api: :oclc)
37
+ @result = search_by(key, query, api: api)
38
+ end
39
+
40
+ # @return [Alexandrite::Book]
41
+ def self.create_book(type, identifier)
42
+ query = Alexandrite::OCLC.new(type, identifier)
43
+ response_code = get_response_code(query.result)
44
+
45
+ response(response_code, query)
46
+ end
47
+ end
48
+
49
+ API = {
50
+ google: Alexandrite::Google,
51
+ oclc: Alexandrite::OCLC
52
+ }.freeze
53
+
54
+ def search_by(key, query, api: :google)
55
+ API[api].search_by(key, query)
56
+ end
57
+
58
+ def create_book(key, query)
59
+ book = API[:google].create_book(query)
60
+ return API[:oclc].create_book(key, query) if book.error_message
61
+
62
+ book
63
+ end
64
+
65
+ # @param isbns [Array]
66
+ # @return [Nil]
67
+ def bulk_create(isbns)
68
+ isbns.each do |isbn|
69
+ volume_info = volume_info(isbn)
70
+ book = Alexandrite::Book.new(volume_info)
71
+ add_to_collection(book)
72
+ end
73
+ nil
74
+ end
75
+
76
+ private
77
+
78
+ def get_volume_info(isbn)
79
+ query = search_by(:isbn, isbn)
80
+ return query[:books].first[:volume_info] unless query[:error_message]
81
+
82
+ query
83
+ end
84
+ end
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'alexandrite'
4
+
5
+ module Alexandrite
6
+ # Create a book objects
7
+ class Book
8
+ attr_accessor :title, :authors, :publisher, :published_date, :page_count, :description, :categories, :language,
9
+ :country, :isbn10, :isbn13, :error_message, :ddc, :lcc, :suggested_classifications
10
+
11
+ # @param volume_info [Hash]
12
+ # @return [Alexandrite::Books]
13
+ def initialize(volume_info)
14
+ add_origin(volume_info)
15
+ add_basic_values(volume_info)
16
+ add_industry_identifiers(volume_info, @origin)
17
+ @error_message = volume_info[:error_message]
18
+ end
19
+
20
+ def self.collection = @@collection
21
+
22
+ def self.add_to_collection(book)
23
+ @@collection.push(book)
24
+ end
25
+
26
+ # @param [String] ddc_code
27
+ # @return [NilClass]
28
+ def add_ddc(ddc_code) = @ddc = ddc_code
29
+
30
+ # @param [String] lcc_code
31
+ # @return [NilClass]
32
+ def add_lcc(lcc_code) = @lcc = lcc_code
33
+
34
+ # @param [Array<String>] suggestions
35
+ # @return [NilClass]
36
+ def add_classification_suggested(suggestions) = @suggested_classifications = suggestions
37
+
38
+ private
39
+
40
+ def add_basic_values(volume_info)
41
+ @title = volume_info['title']
42
+ @authors = volume_info['authors']
43
+ @publisher = volume_info['publisher']
44
+ @published_date = volume_info['publishedDate']
45
+ @page_count = volume_info['pageCount']
46
+ @description = volume_info['description']
47
+ @categories = volume_info['categories']
48
+ @language = volume_info['language']
49
+ end
50
+
51
+ # @param [Hash] volume_info
52
+ # @return [String]
53
+ def add_origin(volume_info) = @origin = volume_info['origin'] || 'Google API'
54
+
55
+ # @param [Hash] volume_info
56
+ # @param [String] origin
57
+ # @return [NilClass]
58
+ def add_industry_identifiers(volume_info, origin)
59
+ return nil unless volume_info[:error_message].nil?
60
+
61
+ if origin == 'OCLC API'
62
+ @isbn10 = volume_info['ISBN_10']
63
+ @isbn13 = volume_info['ISBN_13']
64
+ return
65
+ end
66
+
67
+ volume_info['industryIdentifiers'].each do |identifier|
68
+ @isbn10 = identifier['identifier'] if identifier['type'] == 'ISBN_10'
69
+ @isbn13 = identifier['identifier'] if identifier['type'] == 'ISBN_13'
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'alexandrite'
4
+ require_relative 'book'
5
+
6
+ # Create, Read, Update and Delete books in a book collection
7
+ module Alexandrite
8
+ # Create a collection of books
9
+ class Bookshelf
10
+ def initialize
11
+ @book_collection = []
12
+ end
13
+ end
14
+ def add_book(book) = @book_collection << book if book.instance_of?(Alexandrite::Book)
15
+ end
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ # require all files
4
+ require_relative 'alexandrite/version'
5
+ require 'rubygems'
6
+ require 'faraday'
7
+ require 'json'
8
+ require_relative 'helpers/format'
9
+ require_relative 'helpers/validation'
10
+ require 'pry'
11
+
12
+ module Alexandrite
13
+ # Methods for consuming Google API
14
+ module GoogleAPI
15
+ include Alexandrite::Helpers::Format
16
+ include Alexandrite::Helpers::Validation
17
+
18
+ attr_reader :result, :isbn
19
+
20
+ BASE_URL = 'https://www.googleapis.com/books/v1/volumes?q='
21
+
22
+ FILTERS = {
23
+ author: 'inauthor:',
24
+ isbn: 'isbn:',
25
+ lccn: 'lccn:',
26
+ oclc: 'oclc:',
27
+ publisher: 'inpublisher:',
28
+ subject: 'subject:',
29
+ title: 'intitle:'
30
+ }.freeze
31
+
32
+ FIELDS = {
33
+ title: 'volumeInfo/title',
34
+ authors: 'volumeInfo/authors'
35
+ }.freeze
36
+
37
+ # @param query [String]
38
+ # @return [Faraday::Response]
39
+ def search(query, projection: 'lite')
40
+ conn = Faraday.new("#{BASE_URL}#{query}&projection=#{projection}") do |r|
41
+ r.response :json
42
+ end
43
+
44
+ conn.get.body
45
+ end
46
+
47
+ # @param key [Symbol]
48
+ # @param query [String]
49
+ # @param fields [Array<String>]
50
+ # @return [Faraday::Response]
51
+ def search_by(key, query, projection: 'lite', **fields)
52
+ projection = "&projection=#{projection}"
53
+ url = fields.any? ? "#{BASE_URL}#{FILTERS[key]}#{query}#{add_fields(fields)}#{projection}" : "#{BASE_URL}#{FILTERS[key]}#{query}"
54
+ conn = Faraday.new(url) do |r|
55
+ r.response :json
56
+ end
57
+
58
+ response = conn.get.body
59
+
60
+ process_response(response)
61
+ end
62
+
63
+ private
64
+
65
+ def zero_results?(response_body) = response_body['totalItems'].zero?
66
+
67
+ def process_response(response)
68
+ if zero_results?(response)
69
+ { error_message: 'Not results' }
70
+ else
71
+ { results_size: response['totalItems'],
72
+ books: response['items'] }
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,137 @@
1
+ # frozen_string_literal: true
2
+
3
+ # require all files
4
+ require_relative 'alexandrite/version'
5
+ require 'rubygems'
6
+ require 'faraday'
7
+ require 'faraday/decode_xml'
8
+ require 'json'
9
+ require_relative 'helpers/format'
10
+ require_relative 'helpers/validation'
11
+ require 'pry'
12
+ require 'nokogiri'
13
+
14
+ module Alexandrite
15
+ # Consume OCLC API
16
+ module OCLCAPI
17
+ include Nokogiri
18
+ include Alexandrite::Helpers::Format
19
+ include Alexandrite::Helpers::Validation
20
+
21
+ BASE_URL = 'http://classify.oclc.org/classify2/Classify?'
22
+
23
+ # @param query [String]
24
+ # @return [Faraday::Response]
25
+ def search_by(key, query, summary: true)
26
+ search = "#{BASE_URL}#{key}=#{query}&summary=#{summary}"
27
+ conn = Faraday.new(search) do |r|
28
+ r.get(search).body
29
+ end
30
+ Nokogiri::XML(conn.get(search).body)
31
+ end
32
+
33
+ def get_book_data(result)
34
+ isbn = result.css('input').children.text
35
+ isbn_type = define_isbn_type(isbn)
36
+ {
37
+ 'origin' => 'OCLC API',
38
+ 'title' => result.css('work').attribute('title').value,
39
+ 'authors' => result.css('work').attribute('author').value,
40
+ 'ddc' => result.css('mostPopular').attribute('nsfa').value,
41
+ isbn_type => isbn
42
+ }
43
+ end
44
+
45
+ def recommend_classification(key, query, length = 5, mode: 'ddc')
46
+ results = search_by(key, query)
47
+
48
+ response_cases(results, length, mode)
49
+ end
50
+
51
+ private
52
+
53
+ def get_response_code(result) = result.css('response').attribute('code').value.to_i
54
+
55
+ def get_owis(result, length)
56
+ owis = []
57
+ result.css('work').map { |work| owis << work.attribute('owi').value }
58
+
59
+ owis[0...length]
60
+ end
61
+
62
+ def get_recommendations(owis, mode)
63
+ results = []
64
+ classifications_recommended = []
65
+
66
+ owis.map { |owi_value| results << search_by('owi', owi_value) }
67
+
68
+ results.each do |classification|
69
+ classifications_recommended << get_classification(classification, mode)
70
+ end
71
+
72
+ classifications_recommended
73
+ end
74
+
75
+ def get_classification(result, mode)
76
+ acronym = { 'ddc': 'Dewey Decimal Classification',
77
+ 'lcc': 'Library of Congress Classification' }
78
+
79
+ result.css(mode).css('mostPopular').attribute('nsfa').value
80
+ rescue NoMethodError
81
+ "A #{acronym[mode.to_sym]} is not available for this book"
82
+ end
83
+
84
+ def create_new_book(query)
85
+ volume_info = get_book_data(query.result)
86
+ Alexandrite::Book.new(volume_info)
87
+ end
88
+
89
+ def retry_create_new_book(query)
90
+ owi = get_owis(query.result, 1)[0]
91
+ new_query = Alexandrite::OCLC.new('owi', owi)
92
+ volume_info = get_book_data(new_query.result)
93
+ Alexandrite::Book.new(volume_info)
94
+ end
95
+
96
+ def handle_error_creating_book(query)
97
+ raise ErrorType::DataNotFound, response_cases(query, 0, 'none')
98
+ rescue StandardError => e
99
+ Alexandrite::Book.new('error_message' => e.message)
100
+ end
101
+
102
+ # @param [Nokogiri::XML] result
103
+ # @param [Integer] length
104
+ # @param [String] mode Possible: 'ddc' or 'lcc'
105
+ # @return [String]
106
+ def response_cases(result, length, mode)
107
+ code = get_response_code(result).to_i
108
+ case code
109
+ when 0
110
+ get_classification(result, mode)
111
+ when 2
112
+ get_classification(result, mode)
113
+ when 4
114
+ get_recommendations(get_owis(result, length), mode)
115
+ when 100
116
+ 'No input. The method requires an input argument.'
117
+ when 101
118
+ 'Invalid input. The standard number argument is invalid.'
119
+ when 102
120
+ 'Not found. No data found for the input argument.'
121
+ when 200
122
+ 'Unexpected error.'
123
+ end
124
+ end
125
+
126
+ def response(response_code, query)
127
+ case response_code
128
+ when 0, 2
129
+ create_new_book(query)
130
+ when 4
131
+ retry_create_new_book(query)
132
+ else
133
+ handle_error_creating_book(query)
134
+ end
135
+ end
136
+ end
137
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ErrorType
4
+ class InvalidFormatError < StandardError; end
5
+
6
+ class DataNotFound < StandardError; end
7
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Alexandrite
4
+ module Helpers
5
+ # Format inputs and options
6
+ module Format
7
+ # @param string [String]
8
+ # @return [String]
9
+ def remove_non_digits(string)
10
+ string.gsub!(/[^+\d]/, '')
11
+ end
12
+
13
+ def add_fields(*fields)
14
+ "&fields=items(volumeInfo/#{fields.join(',volumeInfo/')})"
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Alexandrite
4
+ module Helpers
5
+ # Validate inputs
6
+ module Validation
7
+ # @param
8
+ # @return
9
+ def valid_isbn_length?(isbn) = isbn.size == 10 || isbn.size == 13
10
+
11
+ # @param
12
+ # @return [String] or [Nil]
13
+ def validate_isbn(isbn)
14
+ remove_non_digits(isbn.to_s)
15
+ return isbn if valid_isbn_length?(isbn)
16
+
17
+ 'ISBN should have 10 or 13 digits'
18
+ end
19
+
20
+ def define_isbn_type(isbn) = "ISBN_#{isbn.length}"
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: false
2
+
3
+ require 'spec_helper'
4
+ require 'book'
5
+
6
+ RSpec.describe Alexandrite::Book do
7
+ subject { Alexandrite::Book.new('0262033844') }
8
+
9
+ describe 'alexandrite_base' do
10
+ describe '#process' do
11
+ let(:expected_title) { 'Introduction to Algorithms, Third Edition' }
12
+ let(:expected_pages) { 1314 }
13
+ let(:result) { subject.fetch }
14
+
15
+ VCR.use_cassette('get_book') do
16
+ it 'book title' do
17
+ expect(result.title.downcase).to eq(expected_title.downcase)
18
+ end
19
+
20
+ it 'book page count' do
21
+ expect(result.page_count.to_i).to eq(expected_pages)
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Create a book
4
+ FactoryBot.define do
5
+ factory :book do
6
+ isbn { '0262033844' }
7
+ end
8
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: false
2
+
3
+ require 'spec_helper'
4
+ require 'pry'
5
+
6
+ describe 'validate ISBN format' do
7
+ let(:book_class) { Class.new }
8
+
9
+ describe 'valid ISBNs' do
10
+ let(:valid_isbn10) { '0123456789' }
11
+ let(:valid_isbn13) { '1234567890123' }
12
+ let(:valid_isbn_non_digit) { '1-23456789012-3' }
13
+
14
+ it 'valid ISBN of 13 digits' do
15
+ isbn = valid_isbn13
16
+ result = book_class.validate_isbn(isbn)
17
+ expect(result).to eq(valid_isbn13)
18
+ end
19
+
20
+ it 'valid ISBN of 10 digits' do
21
+ result = book_class.validate_isbn(valid_isbn10)
22
+ expect(result).to eq(valid_isbn10)
23
+ end
24
+
25
+ it 'valid ISBN with dashes' do
26
+ result = book_class.validate_isbn(valid_isbn_non_digit)
27
+ expect(result).to eq(valid_isbn13)
28
+ end
29
+ end
30
+
31
+ describe 'invalid ISBNs' do
32
+ let(:error_message) { 'ISBN should have 10 or 13 digits' }
33
+ let(:valid_isbn_white_spaces) { '1234567890123 ' }
34
+ let(:invalid_isbn_non_digit) { 'ABCDEFGHIJ ' }
35
+ let(:invalid_isbn_too_short) { '1234' }
36
+ let(:invalid_isbn_too_long) { '123456789123456789' }
37
+
38
+ it 'ISBN without digits is invalid' do
39
+ result = book_class.validate_isbn(invalid_isbn_non_digit)
40
+ expect(result).to eq(error_message)
41
+ end
42
+
43
+ it 'ISBN is invalid because is too short' do
44
+ result = book_class.validate_isbn(invalid_isbn_too_short)
45
+ expect(result).to eq(error_message)
46
+ end
47
+
48
+ it 'ISBN is invalid because is too long' do
49
+ result = book_class.validate_isbn(invalid_isbn_too_short)
50
+ expect(result).to eq(error_message)
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+ # frozen_string_literal: tru
3
+
4
+ require 'rspec'
5
+ require 'net/http'
6
+ require 'json'
7
+ require 'factory_bot'
8
+ require 'vcr'
9
+ require 'pry-byebug'
10
+ require 'helpers/format'
11
+ require 'support/vcr_setup'
12
+ require 'alexandrite'
13
+
14
+ RSpec.configure do |config|
15
+ config.include FactoryBot::Syntax::Methods
16
+
17
+ config.before(:suite) do
18
+ FactoryBot.find_definitions
19
+ end
20
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'vcr'
4
+
5
+ VCR.configure do |c|
6
+ c.configure_rspec_metadata!
7
+ c.cassette_library_dir = 'vcr/cassettes'
8
+ c.hook_into :webmock
9
+ c.default_cassette_options = {
10
+ erb: true,
11
+ record: :once,
12
+ decode_compressed_response: false,
13
+ match_requests_on: %i[method uri body]
14
+ }
15
+ end
metadata ADDED
@@ -0,0 +1,197 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: alexandrite
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - J. P. Pérez-Tejada
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-01-21 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 2.1.0
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 2.1.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: faraday
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: factory_bot
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: pry-byebug
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rspec-nc
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: vcr
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: webmock
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ description: |-
140
+ Alexandrite is a gem that fetches public book's information by different params based
141
+ on Google Book API and OCLC API . Powered by Faraday.
142
+ email:
143
+ - jpereztejada@apexsystems.com
144
+ - juan@daiuk.com
145
+ executables: []
146
+ extensions: []
147
+ extra_rdoc_files: []
148
+ files:
149
+ - ".gitignore"
150
+ - Gemfile
151
+ - LICENSE
152
+ - README.md
153
+ - Rakefile
154
+ - alexandrite.gemspec
155
+ - lib/alexandrite.rb
156
+ - lib/alexandrite/version.rb
157
+ - lib/alexandrite_books.rb
158
+ - lib/alexandrite_bookshelf.rb
159
+ - lib/alexandrite_google.rb
160
+ - lib/alexandrite_oclc.rb
161
+ - lib/error_type/errors.rb
162
+ - lib/helpers/format.rb
163
+ - lib/helpers/validation.rb
164
+ - spec/alexandrite_spec.rb
165
+ - spec/factories/book.rb
166
+ - spec/helpers/format_spec.rb
167
+ - spec/spec_helper.rb
168
+ - spec/support/vcr_setup.rb
169
+ homepage: https://github.com/maclenn77/alexandrite
170
+ licenses:
171
+ - MIT
172
+ metadata: {}
173
+ post_install_message:
174
+ rdoc_options: []
175
+ require_paths:
176
+ - lib
177
+ required_ruby_version: !ruby/object:Gem::Requirement
178
+ requirements:
179
+ - - ">="
180
+ - !ruby/object:Gem::Version
181
+ version: '3.0'
182
+ required_rubygems_version: !ruby/object:Gem::Requirement
183
+ requirements:
184
+ - - ">="
185
+ - !ruby/object:Gem::Version
186
+ version: '0'
187
+ requirements: []
188
+ rubygems_version: 3.3.3
189
+ signing_key:
190
+ specification_version: 4
191
+ summary: Tools for fetching books data from Google and OCLC
192
+ test_files:
193
+ - spec/alexandrite_spec.rb
194
+ - spec/factories/book.rb
195
+ - spec/helpers/format_spec.rb
196
+ - spec/spec_helper.rb
197
+ - spec/support/vcr_setup.rb