rowling 0.0.2 → 0.0.3
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 +4 -4
- data/README.md +40 -4
- data/lib/rowling.rb +0 -5
- data/lib/rowling/client.rb +27 -17
- data/lib/rowling/exceptions.rb +7 -1
- data/lib/rowling/version.rb +1 -1
- data/test/rowling/client_test.rb +27 -7
- metadata +2 -5
- data/lib/rowling/configuration.rb +0 -21
- data/test/rowling/configuration_test.rb +0 -23
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 978cc635d4f1adaab009a1c5ec5a692603fb47b4
|
4
|
+
data.tar.gz: 818314298ba15aeca00934a6ac4131cb78a6263a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bc998add89f1086f2e78b7ba6c056d7223955db21f2d17e7403637fccf896847ec4f39da52c5b314625bfc207f0097cb469ff768ba82f5a75da91b2ee0bed880
|
7
|
+
data.tar.gz: 0ed29b3964702a83b8f2d7f48885c39cf1dce8be3c4336fce8378a8a61b9e2a092fc8fb790e6b7dcff9a11575cabffdb1eeb0869a75bc0062901bb9d17126421
|
data/README.md
CHANGED
@@ -1,15 +1,16 @@
|
|
1
1
|
# Rowling
|
2
2
|
|
3
|
-
A Ruby wrapper for the USA Today Bestsellers API
|
3
|
+
A Ruby wrapper for the [USA Today Bestsellers API](http://developer.usatoday.com/docs/read/bestselling_books).
|
4
4
|
|
5
5
|
# Usage
|
6
6
|
|
7
|
-
|
7
|
+
First, you'll need an API key, which you can get [here](http://developer.usatoday.com/member/register). Then, you can set up a client:
|
8
8
|
|
9
9
|
```ruby
|
10
10
|
client = Rowling::Client.new(api_key: YOUR_KEY)
|
11
11
|
```
|
12
12
|
|
13
|
+
##Books
|
13
14
|
Search for books included in bestseller lists:
|
14
15
|
|
15
16
|
```ruby
|
@@ -18,9 +19,11 @@ search_params = { author: "J.K. Rowling",
|
|
18
19
|
}
|
19
20
|
|
20
21
|
books = client.search_books(search_params)
|
21
|
-
|
22
22
|
```
|
23
23
|
|
24
|
+
You can view the search parameters [here]( http://developer.usatoday.com/docs/read/bestselling_books#parameters).
|
25
|
+
|
26
|
+
|
24
27
|
This returns an array of Book objects:
|
25
28
|
|
26
29
|
```ruby
|
@@ -40,8 +43,41 @@ Attributes will include:
|
|
40
43
|
title, title_api_url, author, class, description, book_list_appearances, highest_rank, ranks
|
41
44
|
```
|
42
45
|
|
43
|
-
|
46
|
+
##Booklists
|
47
|
+
You can search for book lists by year, month and date. All parameters are optional and without parameters it will retrive the most recent list.
|
44
48
|
|
45
49
|
```ruby
|
46
50
|
client.get_booklists(year: 2015, month: 2)
|
47
51
|
```
|
52
|
+
|
53
|
+
##Other Requests
|
54
|
+
|
55
|
+
```ruby
|
56
|
+
# returns available book classes (fiction vs. nonfiction)
|
57
|
+
client.get_classes
|
58
|
+
|
59
|
+
# returns available book categories
|
60
|
+
client.get_categories
|
61
|
+
|
62
|
+
# returns dates that bestseller lists were published on (can be filtered by using
|
63
|
+
# parameters of month and year, without parameters returns all dates since Oct. 1993)
|
64
|
+
client.get_dates(year: 2015, month: 3)
|
65
|
+
```
|
66
|
+
|
67
|
+
##Options
|
68
|
+
|
69
|
+
If you don't want the responses parsed for you, set up your client with "raw" set to true. The default is false.
|
70
|
+
|
71
|
+
```ruby
|
72
|
+
client = Rowling::Client.new(api_key: YOUR_API_KEY, raw: true)
|
73
|
+
```
|
74
|
+
|
75
|
+
If you would like the client to pause and retry requests when you hit a rate limit, set up your client with "retries" set to the number of times you would like it to retry requests. The default is 0.
|
76
|
+
|
77
|
+
```ruby
|
78
|
+
client = Rowling::Client.new(api_key: YOUR_API_KEY, retries: 2)
|
79
|
+
```
|
80
|
+
|
81
|
+
###Why is it called Rowling?
|
82
|
+
She holds the record for longest #1 USA Today Bestselling Book, with Harry Potter and Sorcerer's Stone topping the list for 31 weeks in 1999. So that's pretty cool.
|
83
|
+
|
data/lib/rowling.rb
CHANGED
@@ -4,13 +4,8 @@ require "addressable/template"
|
|
4
4
|
require "date"
|
5
5
|
require "ext/string.rb"
|
6
6
|
require "rowling/version.rb"
|
7
|
-
require "rowling/configuration.rb"
|
8
7
|
require "rowling/book.rb"
|
9
8
|
require "rowling/rank.rb"
|
10
9
|
require "rowling/exceptions.rb"
|
11
10
|
require "rowling/book_list.rb"
|
12
11
|
require "rowling/client.rb"
|
13
|
-
|
14
|
-
module Rowling
|
15
|
-
extend Configuration
|
16
|
-
end
|
data/lib/rowling/client.rb
CHANGED
@@ -1,12 +1,20 @@
|
|
1
1
|
module Rowling
|
2
2
|
class Client
|
3
3
|
|
4
|
-
|
4
|
+
CONFIGURATION_KEYS = [:api_key, :raw, :retries]
|
5
5
|
|
6
6
|
def initialize(args={})
|
7
|
-
|
7
|
+
CONFIGURATION_KEYS.each do |key|
|
8
8
|
send("#{key}=", args[key])
|
9
9
|
end
|
10
|
+
set_defaults
|
11
|
+
end
|
12
|
+
|
13
|
+
attr_accessor *CONFIGURATION_KEYS
|
14
|
+
|
15
|
+
def set_defaults
|
16
|
+
@raw ||= false
|
17
|
+
@retries ||= 0
|
10
18
|
end
|
11
19
|
|
12
20
|
def base_template
|
@@ -28,10 +36,10 @@ module Rowling
|
|
28
36
|
date_response["Dates"]
|
29
37
|
end
|
30
38
|
|
31
|
-
def search_books(args={}
|
39
|
+
def search_books(args={})
|
32
40
|
segments = "titles"
|
33
41
|
book_response = make_request({segments: segments, query: args})
|
34
|
-
if raw
|
42
|
+
if self.raw
|
35
43
|
book_response
|
36
44
|
else
|
37
45
|
if titles = book_response["Titles"]
|
@@ -44,27 +52,27 @@ module Rowling
|
|
44
52
|
end
|
45
53
|
end
|
46
54
|
|
47
|
-
def find_book_by_isbn(isbn
|
55
|
+
def find_book_by_isbn(isbn)
|
48
56
|
segments = ["titles", isbn]
|
49
|
-
if raw
|
50
|
-
make_request({ segments: segments }
|
57
|
+
if self.raw
|
58
|
+
make_request({ segments: segments })
|
51
59
|
else
|
52
60
|
begin
|
53
61
|
book_response = make_request({ segments: segments })
|
54
62
|
Rowling::Book.new(book_response["Title"])
|
55
|
-
rescue Rowling::Response503Error => e
|
63
|
+
rescue Rowling::Response503Error, Rowling::Response400Error => e
|
56
64
|
return nil
|
57
65
|
end
|
58
66
|
end
|
59
67
|
end
|
60
68
|
|
61
|
-
def get_booklists(args={}
|
69
|
+
def get_booklists(args={})
|
62
70
|
date_segments = [:year, :month, :day].map do |segment|
|
63
71
|
args.delete(segment)
|
64
72
|
end
|
65
73
|
segments = ["booklists"].concat(date_segments.compact)
|
66
74
|
response = make_request({ segments: segments, args: args})
|
67
|
-
if raw
|
75
|
+
if self.raw
|
68
76
|
response
|
69
77
|
elsif lists = response["BookLists"]
|
70
78
|
lists.map{ |list| BookList.new(list) }
|
@@ -73,11 +81,11 @@ module Rowling
|
|
73
81
|
end
|
74
82
|
end
|
75
83
|
|
76
|
-
def get_detailed_version(book
|
84
|
+
def get_detailed_version(book)
|
77
85
|
if book.title_api_url
|
78
86
|
segments = book.title_api_url
|
79
87
|
book_response = make_request({ segments: segments })
|
80
|
-
if raw
|
88
|
+
if self.raw
|
81
89
|
book_response
|
82
90
|
else
|
83
91
|
Rowling::Book.new(book_response["Title"])
|
@@ -87,20 +95,20 @@ module Rowling
|
|
87
95
|
end
|
88
96
|
end
|
89
97
|
|
90
|
-
def make_request(args={},
|
98
|
+
def make_request(args={}, tries=0)
|
91
99
|
if self.api_key
|
92
100
|
uri = build_uri(args)
|
93
101
|
response = HTTParty.get(uri)
|
94
|
-
if raw
|
102
|
+
if self.raw
|
95
103
|
response
|
96
104
|
else
|
97
|
-
if tries <
|
105
|
+
if tries < self.retries
|
98
106
|
begin
|
99
107
|
check_errors(response)
|
100
108
|
rescue Rowling::Response403Error
|
101
109
|
tries += 1
|
102
|
-
sleep(
|
103
|
-
make_request(args,
|
110
|
+
sleep(1)
|
111
|
+
make_request(args, tries)
|
104
112
|
end
|
105
113
|
else
|
106
114
|
check_errors(response)
|
@@ -120,6 +128,8 @@ module Rowling
|
|
120
128
|
def check_errors(response)
|
121
129
|
if response.code == 503
|
122
130
|
raise Rowling::Response503Error
|
131
|
+
elsif response.code == 400
|
132
|
+
raise Rowling::Response400Error
|
123
133
|
elsif response.code == 403
|
124
134
|
raise Rowling::Response403Error
|
125
135
|
elsif response.code != 200
|
data/lib/rowling/exceptions.rb
CHANGED
@@ -5,9 +5,15 @@ module Rowling
|
|
5
5
|
end
|
6
6
|
end
|
7
7
|
|
8
|
+
class Response400Error < StandardError
|
9
|
+
def message
|
10
|
+
"Bad request (data not found)."
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
8
14
|
class Response403Error < StandardError
|
9
15
|
def message
|
10
|
-
"Exceeded quota per second"
|
16
|
+
"Exceeded quota per second/api rate limit"
|
11
17
|
end
|
12
18
|
end
|
13
19
|
|
data/lib/rowling/version.rb
CHANGED
data/test/rowling/client_test.rb
CHANGED
@@ -3,12 +3,16 @@ require 'helper'
|
|
3
3
|
describe Rowling::Client do
|
4
4
|
|
5
5
|
before do
|
6
|
-
@client = Rowling::Client.new(api_key: ENV["USATODAY_BESTSELLER_KEY"]
|
6
|
+
@client = Rowling::Client.new(api_key: ENV["USATODAY_BESTSELLER_KEY"])
|
7
7
|
end
|
8
8
|
|
9
|
-
it "should configure
|
9
|
+
it "should configure an api key" do
|
10
10
|
@client.api_key.must_equal ENV["USATODAY_BESTSELLER_KEY"]
|
11
|
-
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should configure default values for other attributes" do
|
14
|
+
@client.retries.must_equal 0
|
15
|
+
@client.raw.must_equal false
|
12
16
|
end
|
13
17
|
|
14
18
|
it "should raise an error if you try to make a request without an API key" do
|
@@ -17,6 +21,19 @@ describe Rowling::Client do
|
|
17
21
|
end
|
18
22
|
|
19
23
|
describe "requests", :vcr do
|
24
|
+
before do
|
25
|
+
@client.retries = 2
|
26
|
+
end
|
27
|
+
# this is a shitty test but the VCR request it created works for now,
|
28
|
+
# will need to come up with a better one at some point
|
29
|
+
it "should pause and retry when throttled" do
|
30
|
+
retry_client = Rowling::Client.new(api_key: ENV["USATODAY_BESTSELLER_KEY"])
|
31
|
+
3.times do
|
32
|
+
book = @client.find_book_by_isbn("9780758280428")
|
33
|
+
book.must_be_instance_of Rowling::Book
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
20
37
|
it "should get classes" do
|
21
38
|
classes = @client.get_classes
|
22
39
|
classes.must_equal ["---", "Fiction", "NonFiction"]
|
@@ -68,22 +85,25 @@ describe Rowling::Client do
|
|
68
85
|
end
|
69
86
|
|
70
87
|
describe "when raw is set to true" do
|
88
|
+
before do
|
89
|
+
@client.raw = true
|
90
|
+
end
|
71
91
|
|
72
92
|
describe "when searching by ISBN" do
|
73
93
|
|
74
94
|
it "should return a raw response" do
|
75
|
-
response = @client.find_book_by_isbn("9780758280428"
|
95
|
+
response = @client.find_book_by_isbn("9780758280428")
|
76
96
|
response.must_be_instance_of Hash
|
77
97
|
end
|
78
98
|
|
79
99
|
it "should not raise an error when a book is not found" do
|
80
|
-
response = @client.find_book_by_isbn("9781555976859"
|
81
|
-
response.must_be_instance_of
|
100
|
+
response = @client.find_book_by_isbn("9781555976859")
|
101
|
+
response.must_be_instance_of Hash
|
82
102
|
end
|
83
103
|
end
|
84
104
|
|
85
105
|
it "should return a raw response when searching for a book by parameters" do
|
86
|
-
response = @client.search_books({author: "J.K. Rowling"}
|
106
|
+
response = @client.search_books({author: "J.K. Rowling"})
|
87
107
|
response.must_be_instance_of Hash
|
88
108
|
end
|
89
109
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rowling
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sonja Peterson
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-04-
|
11
|
+
date: 2015-04-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -139,7 +139,6 @@ files:
|
|
139
139
|
- lib/rowling/book.rb
|
140
140
|
- lib/rowling/book_list.rb
|
141
141
|
- lib/rowling/client.rb
|
142
|
-
- lib/rowling/configuration.rb
|
143
142
|
- lib/rowling/exceptions.rb
|
144
143
|
- lib/rowling/rank.rb
|
145
144
|
- lib/rowling/version.rb
|
@@ -148,7 +147,6 @@ files:
|
|
148
147
|
- test/rowling/book_list_test.rb
|
149
148
|
- test/rowling/book_test.rb
|
150
149
|
- test/rowling/client_test.rb
|
151
|
-
- test/rowling/configuration_test.rb
|
152
150
|
- test/rowling/rank_test.rb
|
153
151
|
- test/rowling/rowling_test.rb
|
154
152
|
homepage: ''
|
@@ -180,6 +178,5 @@ test_files:
|
|
180
178
|
- test/rowling/book_list_test.rb
|
181
179
|
- test/rowling/book_test.rb
|
182
180
|
- test/rowling/client_test.rb
|
183
|
-
- test/rowling/configuration_test.rb
|
184
181
|
- test/rowling/rank_test.rb
|
185
182
|
- test/rowling/rowling_test.rb
|
@@ -1,21 +0,0 @@
|
|
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
|
@@ -1,23 +0,0 @@
|
|
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
|
-
|