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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 459f9ebfd9177eec1e25a4d6d64ca7c87fe6491f
4
- data.tar.gz: f2e5ca33081dd88320a390dd4fd40be271487584
3
+ metadata.gz: 978cc635d4f1adaab009a1c5ec5a692603fb47b4
4
+ data.tar.gz: 818314298ba15aeca00934a6ac4131cb78a6263a
5
5
  SHA512:
6
- metadata.gz: 6abd827e5307ca49649a09cfde2e12d7ae4ea23161c37830cf53acd3f1bcb3d123c7f55c58faf1c0a4c220453bc412f50fc166c0083653e548b17be374b1991b
7
- data.tar.gz: a47bd8c08307ce0bb56f21de902070ab28ed6d4b999b0b23032688963d639bdb6d748a1cf92f1dcc1ceee411b5890d6831d15c6c3eb90384852c86da66bd7d19
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 (work in progress!)
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
- Set up a client:
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
- 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.
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
@@ -1,12 +1,20 @@
1
1
  module Rowling
2
2
  class Client
3
3
 
4
- attr_accessor *Configuration::CONFIGURATION_KEYS
4
+ CONFIGURATION_KEYS = [:api_key, :raw, :retries]
5
5
 
6
6
  def initialize(args={})
7
- Configuration::CONFIGURATION_KEYS.each do |key|
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={}, raw=false)
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, raw=false)
55
+ def find_book_by_isbn(isbn)
48
56
  segments = ["titles", isbn]
49
- if raw
50
- make_request({ segments: segments }, true)
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={}, raw=false)
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, raw=false)
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={}, raw=false, tries=0)
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 < 2
105
+ if tries < self.retries
98
106
  begin
99
107
  check_errors(response)
100
108
  rescue Rowling::Response403Error
101
109
  tries += 1
102
- sleep(2)
103
- make_request(args, false, tries)
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
@@ -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
 
@@ -1,3 +1,3 @@
1
1
  module Rowling
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
@@ -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"], format: :json)
6
+ @client = Rowling::Client.new(api_key: ENV["USATODAY_BESTSELLER_KEY"])
7
7
  end
8
8
 
9
- it "should configure valid configuration keys" do
9
+ it "should configure an api key" do
10
10
  @client.api_key.must_equal ENV["USATODAY_BESTSELLER_KEY"]
11
- @client.format.must_equal :json
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", true)
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", true)
81
- response.must_be_instance_of String
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"}, true)
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.2
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-15 00:00:00.000000000 Z
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
-