rowling 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +47 -0
- data/Rakefile +10 -0
- data/lib/ext/string.rb +13 -0
- data/lib/rowling/book.rb +26 -0
- data/lib/rowling/book_list.rb +25 -0
- data/lib/rowling/client.rb +132 -0
- data/lib/rowling/configuration.rb +21 -0
- data/lib/rowling/exceptions.rb +22 -0
- data/lib/rowling/rank.rb +16 -0
- data/lib/rowling/version.rb +3 -0
- data/lib/rowling.rb +16 -0
- data/rowling.gemspec +30 -0
- data/test/helper.rb +17 -0
- data/test/rowling/book_list_test.rb +5 -0
- data/test/rowling/book_test.rb +37 -0
- data/test/rowling/client_test.rb +92 -0
- data/test/rowling/configuration_test.rb +23 -0
- data/test/rowling/rank_test.rb +13 -0
- data/test/rowling/rowling_test.rb +7 -0
- metadata +185 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 459f9ebfd9177eec1e25a4d6d64ca7c87fe6491f
|
4
|
+
data.tar.gz: f2e5ca33081dd88320a390dd4fd40be271487584
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6abd827e5307ca49649a09cfde2e12d7ae4ea23161c37830cf53acd3f1bcb3d123c7f55c58faf1c0a4c220453bc412f50fc166c0083653e548b17be374b1991b
|
7
|
+
data.tar.gz: a47bd8c08307ce0bb56f21de902070ab28ed6d4b999b0b23032688963d639bdb6d748a1cf92f1dcc1ceee411b5890d6831d15c6c3eb90384852c86da66bd7d19
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015 sonjapeterson
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
# Rowling
|
2
|
+
|
3
|
+
A Ruby wrapper for the USA Today Bestsellers API (work in progress!)
|
4
|
+
|
5
|
+
# Usage
|
6
|
+
|
7
|
+
Set up a client:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
client = Rowling::Client.new(api_key: YOUR_KEY)
|
11
|
+
```
|
12
|
+
|
13
|
+
Search for books included in bestseller lists:
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
search_params = { author: "J.K. Rowling",
|
17
|
+
title: "Deathly Hallows"
|
18
|
+
}
|
19
|
+
|
20
|
+
books = client.search_books(search_params)
|
21
|
+
|
22
|
+
```
|
23
|
+
|
24
|
+
This returns an array of Book objects:
|
25
|
+
|
26
|
+
```ruby
|
27
|
+
books.first.title = "Harry Potter and the Deathly Hallows"
|
28
|
+
books.first.author = "J.K. Rowling, art by Mary GrandPre"
|
29
|
+
books.first.title_api_url = "/Titles/9780545010221"
|
30
|
+
```
|
31
|
+
|
32
|
+
Books from search only have title, author and api url. For more detailed information, you can find books directly by ISBN:
|
33
|
+
|
34
|
+
```ruby
|
35
|
+
book = client.find_book_by_isbn("9780545010221")
|
36
|
+
```
|
37
|
+
Attributes will include:
|
38
|
+
|
39
|
+
```ruby
|
40
|
+
title, title_api_url, author, class, description, book_list_appearances, highest_rank, ranks
|
41
|
+
```
|
42
|
+
|
43
|
+
You can also search for book lists by year, month and date. All parameters are optional and without parameters it will retrive the most recent list.
|
44
|
+
|
45
|
+
```ruby
|
46
|
+
client.get_booklists(year: 2015, month: 2)
|
47
|
+
```
|
data/Rakefile
ADDED
data/lib/ext/string.rb
ADDED
data/lib/rowling/book.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
module Rowling
|
2
|
+
class Book
|
3
|
+
ATTRIBUTES = [:title, :title_api_url, :author, :class, :description, :book_list_appearances, :highest_rank, :rank_last_week, :isbn, :asin]
|
4
|
+
|
5
|
+
def initialize(response)
|
6
|
+
ATTRIBUTES.each do |key|
|
7
|
+
send("#{key}=", response[key.to_s.camelize]) if response[key.to_s.camelize]
|
8
|
+
end
|
9
|
+
if descrip = response["BriefDescription"]
|
10
|
+
self.description = descrip
|
11
|
+
end
|
12
|
+
if response["Category"]
|
13
|
+
self.category_id = response["Category"]["CategoryID"]
|
14
|
+
self.category_name = response["Category"]["CategoryName"]
|
15
|
+
end
|
16
|
+
if response["RankHistories"]
|
17
|
+
self.ranks = response["RankHistories"].map do |rank|
|
18
|
+
Rowling::Rank.new(rank)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
attr_accessor *ATTRIBUTES, :category_id, :category_name, :ranks
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Rowling
|
2
|
+
class BookList
|
3
|
+
def initialize(response)
|
4
|
+
self.books = parse_entries(response["BookListEntries"])
|
5
|
+
self.date = parse_date(response["BookListDate"])
|
6
|
+
self.name = response["Name"]
|
7
|
+
self.book_list_api_url = response["BookListDate"]["BookListAPIUrl"]
|
8
|
+
end
|
9
|
+
|
10
|
+
attr_accessor :books, :date, :name, :book_list_api_url
|
11
|
+
|
12
|
+
def parse_date(date_response)
|
13
|
+
date_vals = [date_response["Year"], date_response["Month"], date_response["Date"]]
|
14
|
+
date_vals = date_vals.compact.map(&:to_i)
|
15
|
+
Date.new(*date_vals)
|
16
|
+
end
|
17
|
+
|
18
|
+
def parse_entries(entries_response)
|
19
|
+
books = entries_response.map.with_index do |entry, i|
|
20
|
+
[i, book = Rowling::Book.new(entry)]
|
21
|
+
end
|
22
|
+
books.to_h
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
module Rowling
|
2
|
+
class Client
|
3
|
+
|
4
|
+
attr_accessor *Configuration::CONFIGURATION_KEYS
|
5
|
+
|
6
|
+
def initialize(args={})
|
7
|
+
Configuration::CONFIGURATION_KEYS.each do |key|
|
8
|
+
send("#{key}=", args[key])
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def base_template
|
13
|
+
template = Addressable::Template.new("http://api.usatoday.com/open/bestsellers/books{/segments*}{?query*}")
|
14
|
+
end
|
15
|
+
|
16
|
+
def get_classes(args={})
|
17
|
+
class_response = make_request({segments: "classes", query: args})
|
18
|
+
class_response["Classes"]
|
19
|
+
end
|
20
|
+
|
21
|
+
def get_categories(args={})
|
22
|
+
category_response = make_request({segments: "categories", query: args})
|
23
|
+
category_response["Categories"]
|
24
|
+
end
|
25
|
+
|
26
|
+
def get_dates(args={})
|
27
|
+
date_response = make_request({segments: "dates", query: args})
|
28
|
+
date_response["Dates"]
|
29
|
+
end
|
30
|
+
|
31
|
+
def search_books(args={}, raw=false)
|
32
|
+
segments = "titles"
|
33
|
+
book_response = make_request({segments: segments, query: args})
|
34
|
+
if raw
|
35
|
+
book_response
|
36
|
+
else
|
37
|
+
if titles = book_response["Titles"]
|
38
|
+
titles.map do |title|
|
39
|
+
Rowling::Book.new(title)
|
40
|
+
end
|
41
|
+
else
|
42
|
+
[]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def find_book_by_isbn(isbn, raw=false)
|
48
|
+
segments = ["titles", isbn]
|
49
|
+
if raw
|
50
|
+
make_request({ segments: segments }, true)
|
51
|
+
else
|
52
|
+
begin
|
53
|
+
book_response = make_request({ segments: segments })
|
54
|
+
Rowling::Book.new(book_response["Title"])
|
55
|
+
rescue Rowling::Response503Error => e
|
56
|
+
return nil
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def get_booklists(args={}, raw=false)
|
62
|
+
date_segments = [:year, :month, :day].map do |segment|
|
63
|
+
args.delete(segment)
|
64
|
+
end
|
65
|
+
segments = ["booklists"].concat(date_segments.compact)
|
66
|
+
response = make_request({ segments: segments, args: args})
|
67
|
+
if raw
|
68
|
+
response
|
69
|
+
elsif lists = response["BookLists"]
|
70
|
+
lists.map{ |list| BookList.new(list) }
|
71
|
+
else
|
72
|
+
{}
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def get_detailed_version(book, raw=false)
|
77
|
+
if book.title_api_url
|
78
|
+
segments = book.title_api_url
|
79
|
+
book_response = make_request({ segments: segments })
|
80
|
+
if raw
|
81
|
+
book_response
|
82
|
+
else
|
83
|
+
Rowling::Book.new(book_response["Title"])
|
84
|
+
end
|
85
|
+
else
|
86
|
+
raise Rowling::ResponseError "Can't retrieve details for book without title api url set"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def make_request(args={}, raw=false, tries=0)
|
91
|
+
if self.api_key
|
92
|
+
uri = build_uri(args)
|
93
|
+
response = HTTParty.get(uri)
|
94
|
+
if raw
|
95
|
+
response
|
96
|
+
else
|
97
|
+
if tries < 2
|
98
|
+
begin
|
99
|
+
check_errors(response)
|
100
|
+
rescue Rowling::Response403Error
|
101
|
+
tries += 1
|
102
|
+
sleep(2)
|
103
|
+
make_request(args, false, tries)
|
104
|
+
end
|
105
|
+
else
|
106
|
+
check_errors(response)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
else
|
110
|
+
raise Rowling::NoAPIKeyError
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def build_uri(args)
|
115
|
+
query = { "api_key" => self.api_key }
|
116
|
+
query.merge!(args[:query]) if args[:query]
|
117
|
+
base_template.expand({segments: args[:segments], query: query}).to_s
|
118
|
+
end
|
119
|
+
|
120
|
+
def check_errors(response)
|
121
|
+
if response.code == 503
|
122
|
+
raise Rowling::Response503Error
|
123
|
+
elsif response.code == 403
|
124
|
+
raise Rowling::Response403Error
|
125
|
+
elsif response.code != 200
|
126
|
+
raise Rowling::ResponseError, "Request Failed. Code #{response.code}."
|
127
|
+
else
|
128
|
+
response
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Rowling
|
2
|
+
module Configuration
|
3
|
+
DEFAULT_FORMAT = :json
|
4
|
+
CONFIGURATION_KEYS = [:api_key, :format]
|
5
|
+
|
6
|
+
attr_accessor *CONFIGURATION_KEYS
|
7
|
+
|
8
|
+
def self.extended(base)
|
9
|
+
base.reset
|
10
|
+
end
|
11
|
+
|
12
|
+
def reset
|
13
|
+
self.api_key = nil
|
14
|
+
self.format = :json
|
15
|
+
end
|
16
|
+
|
17
|
+
def configure
|
18
|
+
yield self
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Rowling
|
2
|
+
class Response503Error < StandardError
|
3
|
+
def message
|
4
|
+
"Service temporarily unavailable."
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
class Response403Error < StandardError
|
9
|
+
def message
|
10
|
+
"Exceeded quota per second"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class NoAPIKeyError < StandardError
|
15
|
+
def message
|
16
|
+
"You must set a valid API key before making requests"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class ResponseError < StandardError; end
|
21
|
+
|
22
|
+
end
|
data/lib/rowling/rank.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
module Rowling
|
2
|
+
class Rank
|
3
|
+
|
4
|
+
def initialize(response)
|
5
|
+
self.date = Rowling::Rank.parse_rank_date(response["BookListDate"])
|
6
|
+
self.rank = response["Rank"]
|
7
|
+
self.book_list_api_url = response["BookListDate"]["BookListAPIUrl"]
|
8
|
+
end
|
9
|
+
|
10
|
+
attr_accessor :date, :rank, :book_list_api_url
|
11
|
+
|
12
|
+
def self.parse_rank_date(date_response)
|
13
|
+
Date.new(date_response["Year"].to_i, date_response["Month"].to_i, date_response["Date"].to_i)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/rowling.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require "httparty"
|
2
|
+
require "addressable/uri"
|
3
|
+
require "addressable/template"
|
4
|
+
require "date"
|
5
|
+
require "ext/string.rb"
|
6
|
+
require "rowling/version.rb"
|
7
|
+
require "rowling/configuration.rb"
|
8
|
+
require "rowling/book.rb"
|
9
|
+
require "rowling/rank.rb"
|
10
|
+
require "rowling/exceptions.rb"
|
11
|
+
require "rowling/book_list.rb"
|
12
|
+
require "rowling/client.rb"
|
13
|
+
|
14
|
+
module Rowling
|
15
|
+
extend Configuration
|
16
|
+
end
|
data/rowling.gemspec
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'rowling/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "rowling"
|
8
|
+
spec.version = Rowling::VERSION
|
9
|
+
spec.authors = ["Sonja Peterson"]
|
10
|
+
spec.email = ["sonja.peterson@gmail.com"]
|
11
|
+
spec.summary = "Wrapper for USA Today Bestsellers API."
|
12
|
+
spec.description = "A simple Ruby wrapper for accessing USA Today bestseller data."
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.7"
|
22
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
23
|
+
spec.add_development_dependency "minitest-reporters", "~> 1.0.11"
|
24
|
+
spec.add_development_dependency "minitest-vcr", "~> 1.3.0"
|
25
|
+
spec.add_development_dependency "webmock"
|
26
|
+
|
27
|
+
spec.add_dependency "httparty", "~> 0.13.3"
|
28
|
+
spec.add_dependency "addressable", "~> 2.3.6"
|
29
|
+
spec.add_dependency "require_all", "~> 1.3.2"
|
30
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'rowling'
|
2
|
+
require 'minitest/spec'
|
3
|
+
require 'minitest/autorun'
|
4
|
+
require 'minitest/reporters'
|
5
|
+
require 'vcr'
|
6
|
+
require 'minitest-vcr'
|
7
|
+
require 'webmock'
|
8
|
+
require 'pry'
|
9
|
+
|
10
|
+
reporter_options = { color: true }
|
11
|
+
Minitest::Reporters.use! [Minitest::Reporters::DefaultReporter.new(reporter_options)]
|
12
|
+
|
13
|
+
VCR.configure do |c|
|
14
|
+
c.cassette_library_dir = 'test/cassettes'
|
15
|
+
c.hook_into :webmock
|
16
|
+
end
|
17
|
+
MinitestVcr::Spec.configure!
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
describe Rowling::Book do
|
4
|
+
before do
|
5
|
+
@client = Rowling::Client.new(api_key: ENV["USATODAY_BESTSELLER_KEY"], format: :json)
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should parse the attributes of a book from a request when initializing", :vcr do
|
9
|
+
book = @client.find_book_by_isbn("9780758280428")
|
10
|
+
book.title.must_equal " Double Fudge Brownie Murder"
|
11
|
+
book.author.must_equal "Joanne Fluke"
|
12
|
+
book.category_id.must_equal 0
|
13
|
+
book.category_name.must_equal "----"
|
14
|
+
book.book_list_appearances.must_equal 1
|
15
|
+
book.highest_rank.must_equal 39
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should parse rank histories as instances of Rowling::Rank", :vcr do
|
19
|
+
book = @client.find_book_by_isbn("9780758280428")
|
20
|
+
book.ranks.first.must_be_instance_of Rowling::Rank
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should create a book when only given partial data" do
|
24
|
+
response = {
|
25
|
+
"Title" => "Embassytown",
|
26
|
+
"Author" => "China Mieville",
|
27
|
+
"TitleAPIUrl"=> "/Titles/9781451648539"
|
28
|
+
}
|
29
|
+
book = Rowling::Book.new(response)
|
30
|
+
book.title.must_equal "Embassytown"
|
31
|
+
book.author.must_equal "China Mieville"
|
32
|
+
book.title_api_url.must_equal "/Titles/9781451648539"
|
33
|
+
book.category_id.must_equal nil
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
describe Rowling::Client do
|
4
|
+
|
5
|
+
before do
|
6
|
+
@client = Rowling::Client.new(api_key: ENV["USATODAY_BESTSELLER_KEY"], format: :json)
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should configure valid configuration keys" do
|
10
|
+
@client.api_key.must_equal ENV["USATODAY_BESTSELLER_KEY"]
|
11
|
+
@client.format.must_equal :json
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should raise an error if you try to make a request without an API key" do
|
15
|
+
@client.api_key = nil
|
16
|
+
proc { @client.make_request }.must_raise Rowling::NoAPIKeyError
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "requests", :vcr do
|
20
|
+
it "should get classes" do
|
21
|
+
classes = @client.get_classes
|
22
|
+
classes.must_equal ["---", "Fiction", "NonFiction"]
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should find a book based on a valid ISBN" do
|
26
|
+
book = @client.find_book_by_isbn("9780758280428")
|
27
|
+
book.must_be_instance_of Rowling::Book
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should return nil if no book is found by ISBN search" do
|
31
|
+
book = @client.find_book_by_isbn("9781555976859")
|
32
|
+
book.must_be_nil
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should search for books by title" do
|
36
|
+
books = @client.search_books(title: "Gone Girl")
|
37
|
+
books.first.must_be_instance_of Rowling::Book
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should return an empty array if there are no results for a book" do
|
41
|
+
books = @client.search_books(author: "Geoffrey Chaucer")
|
42
|
+
books.must_equal []
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should search for books by multiple parameters" do
|
46
|
+
books = @client.search_books(author: "Diana Gabaldon", book: "A Leaf on the Wind of All Hallows")
|
47
|
+
books.first.must_be_instance_of Rowling::Book
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should get a detailed version of a book found through search" do
|
51
|
+
books = @client.search_books(author: "J.K. Rowling")
|
52
|
+
detailed_book = @client.get_detailed_version(books.first)
|
53
|
+
detailed_book.must_be_instance_of Rowling::Book
|
54
|
+
detailed_book.title.must_equal "Fantastic Beasts & Where to Find Them"
|
55
|
+
detailed_book.ranks.count.must_equal 24
|
56
|
+
detailed_book.category_id.must_equal 140
|
57
|
+
detailed_book.category_name.must_equal "Youth"
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should get a booklist" do
|
61
|
+
booklists = @client.get_booklists(year: 2015, month: 2)
|
62
|
+
booklists.must_be_instance_of Array
|
63
|
+
booklists[0].must_be_instance_of Rowling::BookList
|
64
|
+
booklists[0].date.must_equal Date.new(2015, 2, 26)
|
65
|
+
booklists[0].name.must_equal "Top 150"
|
66
|
+
booklists[0].book_list_api_url.must_equal "BookLists/2015/2/26"
|
67
|
+
booklists[0].books[0].title.must_equal "The Girl on the Train"
|
68
|
+
end
|
69
|
+
|
70
|
+
describe "when raw is set to true" do
|
71
|
+
|
72
|
+
describe "when searching by ISBN" do
|
73
|
+
|
74
|
+
it "should return a raw response" do
|
75
|
+
response = @client.find_book_by_isbn("9780758280428", true)
|
76
|
+
response.must_be_instance_of Hash
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should not raise an error when a book is not found" do
|
80
|
+
response = @client.find_book_by_isbn("9781555976859", true)
|
81
|
+
response.must_be_instance_of String
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should return a raw response when searching for a book by parameters" do
|
86
|
+
response = @client.search_books({author: "J.K. Rowling"}, true)
|
87
|
+
response.must_be_instance_of Hash
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
describe 'configuration' do
|
4
|
+
after do
|
5
|
+
Rowling.reset
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should set json as the default format" do
|
9
|
+
Rowling.format.must_equal :json
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should set the api key's default value as nil" do
|
13
|
+
Rowling.api_key.must_equal nil
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should allow you to set an api key" do
|
17
|
+
Rowling.configure do |config|
|
18
|
+
config.api_key = "my_secret_key"
|
19
|
+
end
|
20
|
+
Rowling.api_key.must_equal "my_secret_key"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
describe Rowling::Rank do
|
4
|
+
it "should convert rank history data to ranks" do
|
5
|
+
rank_history = [
|
6
|
+
{"BookListDate"=>{"Year"=>"2015", "Month"=>"3", "Date"=>"5", "BookListAPIUrl"=>"BookLists/2015/3/5"}, "Rank"=>39}
|
7
|
+
]
|
8
|
+
ranks = rank_history.map{ |rank| Rowling::Rank.new(rank) }
|
9
|
+
ranks.first.date.must_equal Date.new(2015, 3, 5)
|
10
|
+
ranks.first.rank.must_equal 39
|
11
|
+
ranks.first.book_list_api_url.must_equal "BookLists/2015/3/5"
|
12
|
+
end
|
13
|
+
end
|
metadata
ADDED
@@ -0,0 +1,185 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rowling
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Sonja Peterson
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-04-15 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: '1.7'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.7'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: minitest-reporters
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 1.0.11
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 1.0.11
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: minitest-vcr
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 1.3.0
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 1.3.0
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: webmock
|
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: httparty
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 0.13.3
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 0.13.3
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: addressable
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 2.3.6
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 2.3.6
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: require_all
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 1.3.2
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: 1.3.2
|
125
|
+
description: A simple Ruby wrapper for accessing USA Today bestseller data.
|
126
|
+
email:
|
127
|
+
- sonja.peterson@gmail.com
|
128
|
+
executables: []
|
129
|
+
extensions: []
|
130
|
+
extra_rdoc_files: []
|
131
|
+
files:
|
132
|
+
- ".gitignore"
|
133
|
+
- Gemfile
|
134
|
+
- LICENSE.txt
|
135
|
+
- README.md
|
136
|
+
- Rakefile
|
137
|
+
- lib/ext/string.rb
|
138
|
+
- lib/rowling.rb
|
139
|
+
- lib/rowling/book.rb
|
140
|
+
- lib/rowling/book_list.rb
|
141
|
+
- lib/rowling/client.rb
|
142
|
+
- lib/rowling/configuration.rb
|
143
|
+
- lib/rowling/exceptions.rb
|
144
|
+
- lib/rowling/rank.rb
|
145
|
+
- lib/rowling/version.rb
|
146
|
+
- rowling.gemspec
|
147
|
+
- test/helper.rb
|
148
|
+
- test/rowling/book_list_test.rb
|
149
|
+
- test/rowling/book_test.rb
|
150
|
+
- test/rowling/client_test.rb
|
151
|
+
- test/rowling/configuration_test.rb
|
152
|
+
- test/rowling/rank_test.rb
|
153
|
+
- test/rowling/rowling_test.rb
|
154
|
+
homepage: ''
|
155
|
+
licenses:
|
156
|
+
- MIT
|
157
|
+
metadata: {}
|
158
|
+
post_install_message:
|
159
|
+
rdoc_options: []
|
160
|
+
require_paths:
|
161
|
+
- lib
|
162
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - ">="
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '0'
|
167
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
168
|
+
requirements:
|
169
|
+
- - ">="
|
170
|
+
- !ruby/object:Gem::Version
|
171
|
+
version: '0'
|
172
|
+
requirements: []
|
173
|
+
rubyforge_project:
|
174
|
+
rubygems_version: 2.2.2
|
175
|
+
signing_key:
|
176
|
+
specification_version: 4
|
177
|
+
summary: Wrapper for USA Today Bestsellers API.
|
178
|
+
test_files:
|
179
|
+
- test/helper.rb
|
180
|
+
- test/rowling/book_list_test.rb
|
181
|
+
- test/rowling/book_test.rb
|
182
|
+
- test/rowling/client_test.rb
|
183
|
+
- test/rowling/configuration_test.rb
|
184
|
+
- test/rowling/rank_test.rb
|
185
|
+
- test/rowling/rowling_test.rb
|