isbndb 1.5.5 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +19 -0
- data/.rspec +1 -0
- data/.rvmrc +48 -0
- data/.travis.yml +6 -0
- data/Gemfile +2 -14
- data/Gemfile.lock +41 -21
- data/README.markdown +118 -102
- data/Rakefile +6 -46
- data/config/isbndb.example.yml +3 -0
- data/isbndb.gemspec +19 -73
- data/lib/core_extensions/nil.rb +5 -0
- data/lib/core_extensions/string.rb +49 -0
- data/lib/isbndb.rb +9 -113
- data/lib/isbndb/access_key_set.rb +31 -20
- data/lib/isbndb/exceptions.rb +1 -2
- data/lib/isbndb/query.rb +78 -0
- data/lib/isbndb/result.rb +38 -39
- data/lib/isbndb/result_set.rb +32 -33
- data/spec/responses/access_key_error.xml +5 -0
- data/spec/responses/authors_seth.xml +46 -0
- data/spec/responses/books_hello.xml +76 -0
- data/spec/responses/categories_fiction.xml +46 -0
- data/spec/responses/keystats.xml +6 -0
- data/spec/responses/publishers_francis.xml +46 -0
- data/spec/responses/search.xml +76 -0
- data/spec/responses/subjects_ruby.xml +36 -0
- data/spec/spec_helper.rb +14 -0
- data/spec/support/helpers.rb +8 -0
- data/spec/units/access_key_set_spec.rb +98 -0
- data/spec/units/nil_spec.rb +9 -0
- data/spec/units/query_spec.rb +179 -0
- data/spec/units/result_set_spec.rb +89 -0
- data/spec/units/result_spec.rb +105 -0
- data/spec/units/string_spec.rb +118 -0
- metadata +110 -81
- data/.document +0 -5
- data/ACKNOWLEDGEMENTS +0 -3
- data/LICENSE.txt +0 -20
- data/VERSION +0 -1
- data/test/helper.rb +0 -23
- data/test/test_isbndb.rb +0 -77
data/Rakefile
CHANGED
@@ -1,49 +1,9 @@
|
|
1
|
-
require '
|
2
|
-
require '
|
3
|
-
begin
|
4
|
-
Bundler.setup(:default, :development)
|
5
|
-
rescue Bundler::BundlerError => e
|
6
|
-
$stderr.puts e.message
|
7
|
-
$stderr.puts "Run `bundle install` to install missing gems"
|
8
|
-
exit e.status_code
|
9
|
-
end
|
10
|
-
require 'rake'
|
11
|
-
|
12
|
-
require 'jeweler'
|
13
|
-
Jeweler::Tasks.new do |gem|
|
14
|
-
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
15
|
-
gem.name = "isbndb"
|
16
|
-
gem.homepage = "https://github.com/sethvargo/isbndb"
|
17
|
-
gem.license = "MIT"
|
18
|
-
gem.summary = "This gem provides an easy solution for connecting to ISBNdb.com's API"
|
19
|
-
gem.description = "Ruby ISBNdb is a amazingly fast and accurate gem that reads ISBNdb.com's XML API and gives you incredible flexibilty with the results! The gem uses libxml-ruby, the fastest XML parser for Ruby, so you get blazing fast results every time. Additionally, the newest version of the gem also features caching, so developers minimize API-key usage."
|
20
|
-
gem.email = "seth.vargo@gmail.com"
|
21
|
-
gem.authors = ["Seth Vargo"]
|
22
|
-
end
|
23
|
-
Jeweler::RubygemsDotOrgTasks.new
|
24
|
-
|
25
|
-
require 'rake/testtask'
|
26
|
-
Rake::TestTask.new(:test) do |test|
|
27
|
-
test.libs << 'lib' << 'test'
|
28
|
-
test.pattern = 'test/**/test_*.rb'
|
29
|
-
test.verbose = true
|
30
|
-
end
|
31
|
-
|
32
|
-
require 'rcov/rcovtask'
|
33
|
-
Rcov::RcovTask.new do |test|
|
34
|
-
test.libs << 'test'
|
35
|
-
test.pattern = 'test/**/test_*.rb'
|
36
|
-
test.verbose = true
|
37
|
-
end
|
38
|
-
|
39
|
-
task :default => :test
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
require 'rspec/core/rake_task'
|
40
3
|
|
41
|
-
|
42
|
-
RDoc::Task.new do |rdoc|
|
43
|
-
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
4
|
+
RSpec::Core::RakeTask.new(:spec)
|
44
5
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
rdoc.rdoc_files.include('lib/**/*.rb')
|
6
|
+
namespace :test do
|
7
|
+
desc 'Run tests against the CI'
|
8
|
+
task :ci => [:spec]
|
49
9
|
end
|
data/isbndb.gemspec
CHANGED
@@ -1,79 +1,25 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
-
# -*- encoding: utf-8 -*-
|
1
|
+
# encoding: utf-8
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
5
3
|
|
6
4
|
Gem::Specification.new do |s|
|
7
|
-
s.name
|
8
|
-
s.version
|
5
|
+
s.name = 'isbndb'
|
6
|
+
s.version = '2.0.0'
|
7
|
+
s.author = 'Seth Vargo'
|
8
|
+
s.email = 'sethvargo@gmail.com'
|
9
|
+
s.homepage = 'https://github.com/sethvargo/isbndb'
|
10
|
+
s.summary = 'Connect with ISBNdb.com\'s API'
|
11
|
+
s.description = 'Ruby ISBNdb is a amazingly fast and accurate gem that reads ISBNdb.com\'s XML API and gives you incredible flexibilty with the results! The newest version of the gem also features caching, so developers minimize API-key usage.'
|
9
12
|
|
10
|
-
s.
|
11
|
-
s.
|
12
|
-
s.
|
13
|
-
s.
|
14
|
-
s.email = %q{seth.vargo@gmail.com}
|
15
|
-
s.extra_rdoc_files = [
|
16
|
-
"LICENSE.txt",
|
17
|
-
"README.markdown"
|
18
|
-
]
|
19
|
-
s.files = [
|
20
|
-
".document",
|
21
|
-
"ACKNOWLEDGEMENTS",
|
22
|
-
"Gemfile",
|
23
|
-
"Gemfile.lock",
|
24
|
-
"LICENSE.txt",
|
25
|
-
"README.markdown",
|
26
|
-
"Rakefile",
|
27
|
-
"VERSION",
|
28
|
-
"isbndb.gemspec",
|
29
|
-
"lib/isbndb.rb",
|
30
|
-
"lib/isbndb/access_key_set.rb",
|
31
|
-
"lib/isbndb/exceptions.rb",
|
32
|
-
"lib/isbndb/result.rb",
|
33
|
-
"lib/isbndb/result_set.rb",
|
34
|
-
"test/helper.rb",
|
35
|
-
"test/test_isbndb.rb"
|
36
|
-
]
|
37
|
-
s.homepage = %q{https://github.com/sethvargo/isbndb}
|
38
|
-
s.licenses = [%q{MIT}]
|
39
|
-
s.require_paths = [%q{lib}]
|
40
|
-
s.rubygems_version = %q{1.8.5}
|
41
|
-
s.summary = %q{This gem provides an easy solution for connecting to ISBNdb.com's API}
|
13
|
+
s.files = `git ls-files`.split("\n")
|
14
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
15
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
16
|
+
s.require_paths = ["lib"]
|
42
17
|
|
43
|
-
|
44
|
-
|
18
|
+
s.add_development_dependency 'rspec', '~> 2.10.0'
|
19
|
+
s.add_development_dependency 'shoulda', '~> 3.0.1'
|
20
|
+
s.add_development_dependency 'simplecov', '~> 0.6.4'
|
21
|
+
s.add_development_dependency 'webmock', '~> 1.8.7'
|
45
22
|
|
46
|
-
|
47
|
-
|
48
|
-
s.add_runtime_dependency(%q<i18n>, [">= 0"])
|
49
|
-
s.add_runtime_dependency(%q<rake>, [">= 0"])
|
50
|
-
s.add_runtime_dependency(%q<rdoc>, [">= 0"])
|
51
|
-
s.add_runtime_dependency(%q<libxml-ruby>, [">= 1.1.4"])
|
52
|
-
s.add_development_dependency(%q<shoulda>, [">= 0"])
|
53
|
-
s.add_development_dependency(%q<bundler>, [">= 0"])
|
54
|
-
s.add_development_dependency(%q<jeweler>, [">= 0"])
|
55
|
-
s.add_development_dependency(%q<rcov>, [">= 0"])
|
56
|
-
else
|
57
|
-
s.add_dependency(%q<activesupport>, [">= 0"])
|
58
|
-
s.add_dependency(%q<i18n>, [">= 0"])
|
59
|
-
s.add_dependency(%q<rake>, [">= 0"])
|
60
|
-
s.add_dependency(%q<rdoc>, [">= 0"])
|
61
|
-
s.add_dependency(%q<libxml-ruby>, [">= 1.1.4"])
|
62
|
-
s.add_dependency(%q<shoulda>, [">= 0"])
|
63
|
-
s.add_dependency(%q<bundler>, [">= 0"])
|
64
|
-
s.add_dependency(%q<jeweler>, [">= 0"])
|
65
|
-
s.add_dependency(%q<rcov>, [">= 0"])
|
66
|
-
end
|
67
|
-
else
|
68
|
-
s.add_dependency(%q<activesupport>, [">= 0"])
|
69
|
-
s.add_dependency(%q<i18n>, [">= 0"])
|
70
|
-
s.add_dependency(%q<rake>, [">= 0"])
|
71
|
-
s.add_dependency(%q<rdoc>, [">= 0"])
|
72
|
-
s.add_dependency(%q<libxml-ruby>, [">= 1.1.4"])
|
73
|
-
s.add_dependency(%q<shoulda>, [">= 0"])
|
74
|
-
s.add_dependency(%q<bundler>, [">= 0"])
|
75
|
-
s.add_dependency(%q<jeweler>, [">= 0"])
|
76
|
-
s.add_dependency(%q<rcov>, [">= 0"])
|
77
|
-
end
|
23
|
+
s.add_runtime_dependency 'httparty', '~> 0.8.3'
|
24
|
+
s.add_runtime_dependency 'rake', '~> 0.9.2.2'
|
78
25
|
end
|
79
|
-
|
@@ -0,0 +1,49 @@
|
|
1
|
+
class String
|
2
|
+
require 'date'
|
3
|
+
|
4
|
+
def is_plural?
|
5
|
+
self.downcase.pluralize == self.downcase
|
6
|
+
end
|
7
|
+
|
8
|
+
def is_singular?
|
9
|
+
!self.is_plural?
|
10
|
+
end
|
11
|
+
|
12
|
+
def titleize
|
13
|
+
str = self[0].upcase + self[1..-1].downcase
|
14
|
+
end
|
15
|
+
|
16
|
+
def singularize
|
17
|
+
str = self.dup
|
18
|
+
if str[-3..-1] == 'ies'
|
19
|
+
str[0..-4] + 'y'
|
20
|
+
elsif str[-1] == 's'
|
21
|
+
str[0..-2]
|
22
|
+
else
|
23
|
+
str
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def pluralize
|
28
|
+
str = self.dup
|
29
|
+
if str[-1] == 'y'
|
30
|
+
str[0..-2] + 'ies'
|
31
|
+
elsif str[-1] == 's'
|
32
|
+
str
|
33
|
+
else
|
34
|
+
str + 's'
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def blank?
|
39
|
+
dup.strip.length == 0 ? true : false
|
40
|
+
end
|
41
|
+
|
42
|
+
def underscore
|
43
|
+
self.dup.gsub(/::/, '/').
|
44
|
+
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
45
|
+
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
46
|
+
tr("-", "_").
|
47
|
+
downcase
|
48
|
+
end
|
49
|
+
end
|
data/lib/isbndb.rb
CHANGED
@@ -1,116 +1,12 @@
|
|
1
|
-
# require dependencies
|
2
|
-
require 'libxml'
|
3
|
-
require 'active_support/inflector'
|
4
|
-
|
5
|
-
# private sub-classes
|
6
|
-
require 'isbndb/access_key_set'
|
7
|
-
require 'isbndb/exceptions'
|
8
|
-
require 'isbndb/result_set'
|
9
|
-
require 'isbndb/result'
|
10
|
-
|
11
1
|
module ISBNdb
|
12
|
-
|
13
|
-
# class, and handles the processing power.
|
14
|
-
class Query
|
15
|
-
DEFAULT_COLLECTION = :books
|
16
|
-
DEFAULT_RESULTS = :details
|
17
|
-
BASE_URL = "http://isbndb.com/api"
|
18
|
-
|
19
|
-
# Access methods of the access_key_set instance variable. This allows developers to manually
|
20
|
-
# advance, add, remove, and manage keys. See the AccessKeySet class for more information.
|
21
|
-
attr_reader :access_key_set
|
22
|
-
|
23
|
-
# This method sets an array of access_keys to use for making requests to the ISBNdb API.
|
24
|
-
def initialize(access_keys)
|
25
|
-
@access_key_set = ISBNdb::AccessKeySet.new(access_keys)
|
26
|
-
end
|
27
|
-
|
28
|
-
# This is the generic find method. It accepts a hash of parameters including :collection,
|
29
|
-
# :where clauses, and :results to show. It builds the corresponding URI and sends that URI
|
30
|
-
# off to the ResultSet for processing.
|
31
|
-
def find(params = {})
|
32
|
-
raise "No parameters specified! You must specify at least one parameter!" unless params[:where]
|
33
|
-
|
34
|
-
collection = params[:collection] ||= DEFAULT_COLLECTION
|
35
|
-
results = params[:results] ||= DEFAULT_RESULTS
|
36
|
-
results = [results].flatten
|
37
|
-
|
38
|
-
# build the search clause
|
39
|
-
searches = []
|
40
|
-
params[:where].each_with_index do |(key,val), i|
|
41
|
-
searches << "index#{i+1}=#{key.to_s.strip}"
|
42
|
-
searches << "value#{i+1}=#{val.to_s.strip}"
|
43
|
-
end
|
44
|
-
|
45
|
-
# make the request
|
46
|
-
make_request(collection, results, searches)
|
47
|
-
end
|
48
|
-
|
49
|
-
# This method returns keystats about your API key, including the number of requests
|
50
|
-
# and the number of granted requets. Be advised that this request actually counts
|
51
|
-
# as a request to the server, so use with caution.
|
52
|
-
def keystats
|
53
|
-
uri = "#{BASE_URL}/books.xml?access_key=#{@access_key_set.current_key}&results=keystats"
|
54
|
-
keystats = {}
|
55
|
-
LibXML::XML::Parser.file(uri).parse.find('KeyStats').first.attributes.each { |attribute| keystats[attribute.name.to_sym] = attribute.value.to_i unless attribute.name == 'access_key' }
|
56
|
-
return keystats
|
57
|
-
end
|
58
|
-
|
59
|
-
# Method missing allows for dynamic finders, similar to that of ActiveRecord. See
|
60
|
-
# the README for more information on using magic finders.
|
61
|
-
def method_missing(m, *args, &block)
|
62
|
-
m = m.to_s.downcase
|
63
|
-
|
64
|
-
if m.match(/find_(.+)_by_(.+)/)
|
65
|
-
split = m.split('_', 4)
|
66
|
-
collection, search_strs = split[1].downcase.pluralize, [split.last]
|
67
|
-
|
68
|
-
# check and see if we are searching multiple fields
|
69
|
-
search_strs = search_strs.first.split('_and_') if(search_strs.first.match(/_and_/))
|
70
|
-
raise "Wrong Number of Arguments (#{args.size} for #{search_strs.size})" if args.size != search_strs.size
|
71
|
-
|
72
|
-
# create the searches hash
|
73
|
-
searches = {}
|
74
|
-
search_strs.each_with_index { |str, i| searches[str.strip.to_sym] = args[i].strip }
|
75
|
-
|
76
|
-
return find(:collection => collection, :where => searches)
|
77
|
-
end
|
78
|
-
|
79
|
-
super
|
80
|
-
end
|
81
|
-
|
82
|
-
# Pretty print the Query object with the access key.
|
83
|
-
def to_s
|
84
|
-
"#<ISBNdb::Query, @access_key=#{@access_key_set.current_key}>"
|
85
|
-
end
|
86
|
-
|
87
|
-
private
|
88
|
-
# Make the request to the ResultSet. If the request fails because of an ISBNdb::AccessKeyError
|
89
|
-
# the system will automatically rollover to the next AccessKey in the AccessKeySet. If one exists,
|
90
|
-
# a new request is attempted. If not, the ISBNdb::AccessKeyError persists and can be caught by your
|
91
|
-
# application logic.
|
92
|
-
def make_request(collection, results, searches)
|
93
|
-
begin
|
94
|
-
uri = "#{BASE_URL}/#{collection}.xml?access_key=#{@access_key_set.current_key}&results=#{results.join(',')}&#{searches.join('&')}"
|
95
|
-
ISBNdb::ResultSet.new(uri, collection.singularize.capitalize)
|
96
|
-
rescue ISBNdb::AccessKeyError
|
97
|
-
puts "Access Key Error (#{@access_key_set.current_key}) - You probably reached your limit! Trying the next key."
|
98
|
-
@access_key_set.next_key!
|
99
|
-
retry unless @access_key_set.current_key.nil?
|
100
|
-
raise ISBNdb::AccessKeyError
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|
104
|
-
end
|
2
|
+
require 'httparty'
|
105
3
|
|
4
|
+
require 'isbndb/access_key_set'
|
5
|
+
require 'isbndb/exceptions'
|
6
|
+
require 'isbndb/query'
|
7
|
+
require 'isbndb/result_set'
|
8
|
+
require 'isbndb/result'
|
106
9
|
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
self.downcase.pluralize == self.downcase
|
111
|
-
end
|
112
|
-
|
113
|
-
def is_singular?
|
114
|
-
!self.is_plural?
|
115
|
-
end
|
116
|
-
end
|
10
|
+
require 'core_extensions/string'
|
11
|
+
require 'core_extensions/nil'
|
12
|
+
end
|
@@ -1,53 +1,64 @@
|
|
1
1
|
module ISBNdb
|
2
|
-
|
3
|
-
private
|
2
|
+
protected
|
4
3
|
# The AccessKeySet is a simple class used to manage access keys. It is used primarily
|
5
4
|
# by the ruby_isbndb class to automatically advance access keys when necessary.
|
6
5
|
class AccessKeySet
|
7
6
|
# Create the @access_keys array and then verify that the keys are valid keys.
|
8
|
-
def initialize
|
9
|
-
@access_keys
|
7
|
+
def initialize
|
8
|
+
@access_keys ||= YAML::load(File.open('config/isbndb.yml'))['access_keys']
|
10
9
|
end
|
11
|
-
|
10
|
+
|
11
|
+
# Returns the total number of access keys in this set.
|
12
|
+
def size
|
13
|
+
@access_keys.size
|
14
|
+
end
|
15
|
+
|
16
|
+
def current_index
|
17
|
+
@current_index ||= 0
|
18
|
+
end
|
19
|
+
|
12
20
|
# Get the current key. It returns a string of the access key.
|
13
21
|
def current_key
|
14
|
-
@access_keys[
|
22
|
+
@access_keys[current_index]
|
15
23
|
end
|
16
|
-
|
24
|
+
|
17
25
|
# Move the key pointer forward.
|
18
26
|
def next_key!
|
19
|
-
@current_index
|
27
|
+
@current_index = current_index + 1
|
28
|
+
current_key
|
20
29
|
end
|
21
|
-
|
30
|
+
|
22
31
|
# Get the next key.
|
23
32
|
def next_key
|
24
|
-
@access_keys[
|
33
|
+
@access_keys[current_index+1]
|
25
34
|
end
|
26
|
-
|
35
|
+
|
27
36
|
# Move the key pointer back.
|
28
37
|
def prev_key!
|
29
|
-
@current_index
|
38
|
+
@current_index = current_index - 1
|
39
|
+
current_key
|
30
40
|
end
|
31
|
-
|
41
|
+
|
32
42
|
# Get the previous key.
|
33
43
|
def prev_key
|
34
|
-
@access_keys[
|
44
|
+
@access_keys[current_index-1]
|
35
45
|
end
|
36
|
-
|
37
|
-
# Tell Ruby ISBNdb to use a specified key. If the key does not exist, it is
|
46
|
+
|
47
|
+
# Tell Ruby ISBNdb to use a specified key. If the key does not exist, it is
|
38
48
|
# added to the set and set as the current key.
|
39
49
|
def use_key(key)
|
40
50
|
@current_index = @access_keys.index(key) || @access_keys.push(key).index(key)
|
51
|
+
current_key
|
41
52
|
end
|
42
|
-
|
53
|
+
|
43
54
|
# Remove the given access key from the AccessKeySet.
|
44
55
|
def remove_key(key)
|
45
56
|
@access_keys.delete(key)
|
46
57
|
end
|
47
|
-
|
58
|
+
|
48
59
|
# Pretty print the AccessKeySet
|
49
60
|
def to_s
|
50
|
-
"#<AccessKeySet @keys
|
61
|
+
"#<AccessKeySet @keys=#{@access_keys.inspect}>"
|
51
62
|
end
|
52
63
|
end
|
53
|
-
end
|
64
|
+
end
|
data/lib/isbndb/exceptions.rb
CHANGED
data/lib/isbndb/query.rb
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
module ISBNdb
|
2
|
+
# The Query object is the most important class of the ISBNdb Module. It is the only public
|
3
|
+
# class, and handles the processing power.
|
4
|
+
class Query
|
5
|
+
include HTTParty
|
6
|
+
base_uri 'http://isbndb.com/api'
|
7
|
+
headers 'Content-Type' => 'text/xml'
|
8
|
+
|
9
|
+
# This is the generic find method. It accepts a hash of parameters including :collection,
|
10
|
+
# :where clauses, and :results to show. It builds the corresponding URI and sends that URI
|
11
|
+
# off to the ResultSet for processing.
|
12
|
+
def self.find(params = {})
|
13
|
+
raise 'No parameters specified! You must specify at least one parameter!' unless params[:where]
|
14
|
+
raise 'params[:where] cannot be a String! It must be a Hash!' if params[:where].is_a?(String)
|
15
|
+
raise 'params[:where] cannot be an Array! It must be a Hash!' if params[:where].is_a?(Array)
|
16
|
+
|
17
|
+
collection = params[:collection] ||= :books
|
18
|
+
results = params[:results] ||= :details
|
19
|
+
results = [results].flatten
|
20
|
+
|
21
|
+
# build the search clause
|
22
|
+
searches = []
|
23
|
+
params[:where].each_with_index do |(key,val), i|
|
24
|
+
searches << "index#{i+1}=#{key.to_s.strip}"
|
25
|
+
searches << "value#{i+1}=#{val.to_s.strip}"
|
26
|
+
end
|
27
|
+
|
28
|
+
# make the request
|
29
|
+
uri = "/#{collection}.xml?access_key=#{access_key_set.current_key}&results=#{results.join(',')}&#{searches.join('&')}"
|
30
|
+
ISBNdb::ResultSet.new(uri, collection)
|
31
|
+
rescue ISBNdb::AccessKeyError
|
32
|
+
access_key_set.next_key!
|
33
|
+
retry unless access_key_set.current_key.nil?
|
34
|
+
raise
|
35
|
+
end
|
36
|
+
|
37
|
+
# This method returns keystats about your API key, including the number of requests
|
38
|
+
# and the number of granted requets. Be advised that this request actually counts
|
39
|
+
# as a request to the server, so use with caution.
|
40
|
+
def self.keystats
|
41
|
+
result = self.get("/books.xml?access_key=#{access_key_set.current_key}&results=keystats")
|
42
|
+
result.parsed_response['ISBNdb']['KeyStats'] || {}
|
43
|
+
end
|
44
|
+
|
45
|
+
# Method missing allows for dynamic finders, similar to that of ActiveRecord. See
|
46
|
+
# the README for more information on using magic finders.
|
47
|
+
def self.method_missing(m, *args, &block)
|
48
|
+
method = m.to_s.downcase
|
49
|
+
|
50
|
+
if method.match(/find_(.+)_by_(.+)/)
|
51
|
+
split = method.split('_', 4)
|
52
|
+
collection, search_strs = split[1].downcase.pluralize, [split.last]
|
53
|
+
|
54
|
+
# check and see if we are searching multiple fields
|
55
|
+
search_strs = search_strs.first.split('_and_') if(search_strs.first.match(/_and_/))
|
56
|
+
raise "Wrong Number of Arguments (#{args.size} for #{search_strs.size})" if args.size != search_strs.size
|
57
|
+
|
58
|
+
# create the searches hash
|
59
|
+
searches = {}
|
60
|
+
search_strs.each_with_index { |str, i| searches[str.strip.to_sym] = args[i].strip }
|
61
|
+
|
62
|
+
return find(:collection => collection, :where => searches)
|
63
|
+
end
|
64
|
+
|
65
|
+
super
|
66
|
+
end
|
67
|
+
|
68
|
+
# Pretty print the Query object with the access key.
|
69
|
+
def self.to_s
|
70
|
+
"#<ISBNdb::Query, @access_key=#{access_key_set.current_key}>"
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
def self.access_key_set
|
75
|
+
@@access_key_set ||= ISBNdb::AccessKeySet.new
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|