giant_bomb_api 0.5.1 → 0.5.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6fd8d486158ad9852607a5d5449d7c178231d240
4
- data.tar.gz: 6db2a32b7bb1b96b9c0b2558f049f777aba75347
3
+ metadata.gz: 96c196f26a23e4fc41d2dd883f939c8c83e062c7
4
+ data.tar.gz: 6b6739d5ce1ffb80772ad6c4a42643c9e8ae98ba
5
5
  SHA512:
6
- metadata.gz: e4c734f8103a813df3ed478f91066c14639282e48d3229b6274c01ad594e990455bfcb14b546d30f02095c6eeb06fe417b1373a7feaaf3245e53e557347e21fc
7
- data.tar.gz: 148e746b6817d37b70cd31511c2a9419169dec0d18c781198ef5015a984fd6bdb92907da0c725e9a7a1e7bcad9ef830e6f907dcdfa9fab73c0558a564d78ee26
6
+ metadata.gz: 434798f04cdb4329fbee5ac8dd25de961865488a5d9a875973c009169255c56be6d69dfbc9f50abde08d7f0123bc530db6a2ade93e0bb6b3f706b022dcd9c58a
7
+ data.tar.gz: 53ed38aebfd37671baa86fd6791c1c1a0809e9a31df3ddb035d6c0d4d72f17d2b67da0901122cf3fb409148faf5ab82da2624084a5b44aa190fe94dc9d1757c5
data/.gitignore CHANGED
@@ -1,3 +1,4 @@
1
1
  bin
2
2
  coverage
3
- *.gem
3
+ *.gem
4
+ Gemfile.lock
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2.2
4
+ script: "bundle exec rspec && bundle exec codeclimate-test-reporter"
data/README.md CHANGED
@@ -6,12 +6,14 @@ This gem aims to provide access to most endpoints on the API. You'll be able to
6
6
 
7
7
  **Contributors are welcome**. Please contact [@toadle](https://github.com/toadle).
8
8
 
9
+ [![Gem Version](https://badge.fury.io/rb/giant_bomb_api.svg)](http://badge.fury.io/rb/giant_bomb_api)
9
10
  [![Code Climate](https://codeclimate.com/github/toadle/giant_bomb_api/badges/gpa.svg)](https://codeclimate.com/github/toadle/giant_bomb_api)
10
11
  [![Test Coverage](https://codeclimate.com/github/toadle/giant_bomb_api/badges/coverage.svg)](https://codeclimate.com/github/toadle/giant_bomb_api/coverage)
11
- [![Circle CI](https://circleci.com/gh/toadle/giant_bomb_api/tree/dev.svg?style=svg)](https://circleci.com/gh/toadle/giant_bomb_api/tree/dev)
12
+ [![Travis CI](https://travis-ci.org/toadle/giant_bomb_api.svg?branch=dev)](https://travis-ci.org/toadle/giant_bomb_api)
12
13
 
13
14
  ## Changelog
14
- * **2015-09-19**: Initial release as 0.5
15
+ * **2017-06-30**: `each_page`-iterator instead of `all`, which supports rate-limiting. Thanks to @naiyt
16
+ * **2015-09-19**: Initial release as 0.5.1
15
17
 
16
18
  # Installation
17
19
 
@@ -24,7 +26,7 @@ gem install giant_bomb_api
24
26
  or in your `Gemfile`
25
27
 
26
28
  ```
27
- gem giant_bomb_api
29
+ gem 'giant_bomb_api'
28
30
  ```
29
31
 
30
32
  # How to use
@@ -116,16 +118,28 @@ You can also directly query a resource that has a collection-endpoint.
116
118
 
117
119
  This is available for all resources that the [Giantbomb API](http://www.giantbomb.com/api/documentation) offers a 'collection' for. e.g. `game` and `games`or `character` and `characters`.
118
120
 
119
- e.g. all:
121
+ Use the `each_page` method to iterate through each page of a collection. `each_page` will accept a block and pass it the current page of results.
120
122
 
121
- ```
122
- GiantBombApi::Resource::Game.all
123
+ ```ruby
124
+ GiantBombApi::Resource::Game.each_page do |page|
125
+ names = page.results.map(&:name)
126
+ puts names
127
+ end
123
128
  ```
124
129
 
125
- this call supports optional sorting, e.g.:
130
+ `each_page` accepts the following optional keyword arguments:
126
131
 
127
- ```
128
- GiantBombApi::Resource::Game.all(sort: { name: :desc })
132
+ - `sort`: a sort option for the results
133
+ - `limit`: the number of results to return per page. Defaults to 100 (the max allowed through the Giant Bomb API)
134
+ - `offset`: defaults to 0
135
+ - `should_rate_limit`: pass this in as true if you want to ensure that you are rate limiting your requests to under the required 200 per resource per hour (which is important if you're trying to iterate through every page of a resource)
136
+
137
+ Example using the optional arguments:
138
+
139
+ ```ruby
140
+ GiantBombApi::Resource::Game.each_page(sort: { name: :desc }, limit: 50, should_rate_limit: true) do |page|
141
+ # do something with the page
142
+ end
129
143
  ```
130
144
 
131
145
  if you want to get more detailed your can do:
@@ -1,10 +1,10 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "giant_bomb_api"
3
- s.version = "0.5.1"
3
+ s.version = "0.5.2"
4
4
  s.default_executable = "giantbomb"
5
5
 
6
6
  s.authors = ["Tim Adler"]
7
- s.date = %q{2015-09-19}
7
+ s.date = %q{2017-06-30}
8
8
  s.description = %q{An unofficial ruby wrapper for the Giantbomb API (http://api.giantbomb.com). An API that provides structured data about videogames.}
9
9
  s.summary = s.description
10
10
  s.email = %q{mail (at) toadle (dot) me}
@@ -25,7 +25,8 @@ Gem::Specification.new do |s|
25
25
  s.add_development_dependency 'rspec', '~> 3.0'
26
26
  s.add_development_dependency 'pry-byebug'
27
27
  s.add_development_dependency 'timecop'
28
+ s.add_development_dependency 'simplecov'
29
+ s.add_development_dependency 'rubocop'
28
30
  s.add_development_dependency 'codeclimate-test-reporter'
29
31
 
30
32
  end
31
-
@@ -12,8 +12,13 @@ module GiantBombApi
12
12
  self.instance_variable_get("@collection_resource_name") || self.resource_name.pluralize
13
13
  end
14
14
 
15
- def all(sort = {})
16
- where(sort: sort)
15
+ def each_page(sort: {}, limit: 100, offset: 0, should_rate_limit: false)
16
+ rate_limit(should_rate_limit) do
17
+ response = where(sort: sort, limit: limit, offset: offset, tries: 5)
18
+ yield response
19
+ offset += limit
20
+ break unless response.has_more_results?
21
+ end
17
22
  end
18
23
 
19
24
  def find(id, params = {})
@@ -26,6 +31,7 @@ module GiantBombApi
26
31
  sort = params[:sort]
27
32
  limit = params[:limit]
28
33
  offset = params[:offset]
34
+ tries ||= (params[:tries] || 0)
29
35
 
30
36
  args = {}
31
37
  args[:filter] = params.reject {|key,value| %i(sort limit offset).include?(key) }
@@ -34,7 +40,42 @@ module GiantBombApi
34
40
  args[:offset] = offset if offset.present?
35
41
 
36
42
  GiantBombApi.client.send_request(Request::Collection.new(self, args))
43
+ rescue Faraday::ConnectionFailed, Faraday::TimeoutError => e
44
+ if (tries -= 1) > 0
45
+ sleep 5
46
+ retry
47
+ end
48
+
49
+ raise e
50
+ end
51
+
52
+ private
53
+
54
+ def rate_limit(should_rate_limit, &block)
55
+ started_at = Time.now
56
+ num_of_requests = 0
57
+
58
+ loop do
59
+ t1 = Time.now
60
+ block.call
61
+ num_of_requests += 1
62
+ t2 = Time.now
63
+
64
+ if should_rate_limit
65
+ if t2 - started_at >= 1.hour
66
+ started_at = Time.now
67
+ num_of_requests = 0
68
+ end
69
+
70
+ request_time = t2 - t1
71
+ time_to_one_hour = (started_at + 1.hour) - t2
72
+ remaining_requests = 200 - num_of_requests
73
+ min_time_per_request = time_to_one_hour / remaining_requests
74
+
75
+ sleep(min_time_per_request - request_time) if request_time < min_time_per_request
76
+ end
77
+ end
37
78
  end
38
79
 
39
80
  end
40
- end
81
+ end
@@ -34,43 +34,70 @@ describe GiantBombApi::CollectionResource do
34
34
 
35
35
  end
36
36
 
37
- describe '#where' do
37
+ describe 'query methods' do
38
38
  let(:client) { double("GiantBombApi::Client") }
39
- before do
39
+ let(:dummy_collection_request) { double("DummyCollectionRequest") }
40
+ let(:response) { double("GiantBombApi::Response") }
41
+
42
+ before do
40
43
  allow(GiantBombApi).to receive(:client).and_return(client)
41
44
  end
42
45
 
43
- context "when given NO additional attributes" do
44
- let(:dummy_collection_request) { double("DummyCollectionRequest") }
45
- let(:response) { double("GiantBombApi::Response") }
46
+ describe '#where' do
47
+ context "when given NO additional attributes" do
48
+ it 'will send a blank collection-request for itself' do
49
+ expect(GiantBombApi::Request::Collection).to receive(:new).with(DummyCollection).and_return(dummy_collection_request)
50
+ expect(client).to receive(:send_request).with(dummy_collection_request).and_return(response)
51
+ expect(DummyCollection.where).to eq response
52
+ end
53
+ end
46
54
 
47
- it 'will send a blank collection-request for itself' do
48
- expect(GiantBombApi::Request::Collection).to receive(:new).with(DummyCollection).and_return(dummy_collection_request)
49
- expect(client).to receive(:send_request).with(dummy_collection_request).and_return(response)
50
- expect(DummyCollection.where).to eq response
55
+ context "when given a hash that does not contain :sort, :offset or :limit" do
56
+ it 'will send a collection-request with the given has as a filter' do
57
+ expect(GiantBombApi::Request::Collection).to receive(:new).with(DummyCollection, filter: { name: "something", aliases: "other" }).and_return(dummy_collection_request)
58
+ expect(client).to receive(:send_request).with(dummy_collection_request).and_return(response)
59
+ expect(DummyCollection.where(name: "something", aliases: "other")).to eq response
60
+ end
51
61
  end
52
- end
53
- context "when given a hash that does not contain :sort, :offset or :limit" do
54
- let(:dummy_collection_request) { double("DummyCollectionRequest") }
55
- let(:response) { double("GiantBombApi::Response") }
56
-
57
- it 'will send a collection-request with the given has as a filter' do
58
- expect(GiantBombApi::Request::Collection).to receive(:new).with(DummyCollection, filter: { name: "something", aliases: "other" }).and_return(dummy_collection_request)
59
- expect(client).to receive(:send_request).with(dummy_collection_request).and_return(response)
60
- expect(DummyCollection.where(name: "something", aliases: "other")).to eq response
62
+
63
+ context "when given a hash that contains :sort, :offset and :limit" do
64
+ it 'will send a collection-request with the the parameters assorted correctly' do
65
+ expect(GiantBombApi::Request::Collection).to receive(:new).with(DummyCollection, filter: { name: "something", aliases: "other" }, sort: {something: :desc}, limit: 10, offset: 1).and_return(dummy_collection_request)
66
+ expect(client).to receive(:send_request).with(dummy_collection_request).and_return(response)
67
+ expect(DummyCollection.where(name: "something", aliases: "other", sort: {something: :desc}, limit: 10, offset: 1)).to eq response
68
+ end
61
69
  end
62
70
  end
63
71
 
64
- context "when given a hash that contains :sort, :offset and :limit" do
65
- let(:dummy_collection_request) { double("DummyCollectionRequest") }
66
- let(:response) { double("GiantBombApi::Response") }
72
+ describe '#each_page' do
73
+ it 'will continually retrieve the next page until there are no more results' do
74
+ expect(DummyCollection).to receive(:where).and_return(dummy_collection_request).exactly(5).times
75
+ allow(dummy_collection_request).to receive(:has_more_results?).and_return(true)
76
+
77
+ times = 0
78
+ DummyCollection.each_page do |page|
79
+ times += 1
80
+ if times == 5
81
+ allow(dummy_collection_request).to receive(:has_more_results?).and_return(false)
82
+ end
83
+ end
84
+ end
67
85
 
68
- it 'will send a collection-request with the the parameters assorted correctly' do
69
- expect(GiantBombApi::Request::Collection).to receive(:new).with(DummyCollection, filter: { name: "something", aliases: "other" }, sort: {something: :desc}, limit: 10, offset: 1).and_return(dummy_collection_request)
70
- expect(client).to receive(:send_request).with(dummy_collection_request).and_return(response)
71
- expect(DummyCollection.where(name: "something", aliases: "other", sort: {something: :desc}, limit: 10, offset: 1)).to eq response
86
+ context 'with should_rate_limit set to true' do
87
+ it 'will rate limit the calls so that there are not more than 200 per hour' do
88
+ expect(DummyCollection).to receive(:where).and_return(dummy_collection_request).exactly(3).times
89
+ allow(dummy_collection_request).to receive(:has_more_results?).and_return(true)
90
+ expect(DummyCollection).to receive(:sleep).twice
91
+
92
+ times = 0
93
+ DummyCollection.each_page(should_rate_limit: true) do |page|
94
+ times += 1
95
+ if times == 3
96
+ allow(dummy_collection_request).to receive(:has_more_results?).and_return(false)
97
+ end
98
+ end
99
+ end
72
100
  end
73
101
  end
74
102
  end
75
-
76
103
  end
data/spec/spec_helper.rb CHANGED
@@ -1,10 +1,9 @@
1
- require "codeclimate-test-reporter"
2
- CodeClimate::TestReporter.start
3
-
4
1
  require 'giant_bomb_api'
5
2
  require 'rspec'
6
3
  require 'timecop'
7
4
  require 'pry-byebug'
5
+ require 'simplecov'
6
+ SimpleCov.start
8
7
 
9
8
  RSpec.configure do |config|
10
9
 
@@ -12,4 +11,4 @@ RSpec.configure do |config|
12
11
  Timecop.return
13
12
  end
14
13
 
15
- end
14
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: giant_bomb_api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.1
4
+ version: 0.5.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tim Adler
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-09-19 00:00:00.000000000 Z
11
+ date: 2017-06-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -122,6 +122,34 @@ dependencies:
122
122
  - - ">="
123
123
  - !ruby/object:Gem::Version
124
124
  version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: simplecov
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
+ - !ruby/object:Gem::Dependency
140
+ name: rubocop
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
125
153
  - !ruby/object:Gem::Dependency
126
154
  name: codeclimate-test-reporter
127
155
  requirement: !ruby/object:Gem::Requirement
@@ -148,12 +176,11 @@ files:
148
176
  - ".rubocop.yml"
149
177
  - ".ruby-gemset"
150
178
  - ".ruby-version"
179
+ - ".travis.yml"
151
180
  - Gemfile
152
- - Gemfile.lock
153
181
  - LICENSE
154
182
  - README.md
155
183
  - Rakefile
156
- - circle.yml
157
184
  - giant_bomb_api.gemspec
158
185
  - lib/giant_bomb_api.rb
159
186
  - lib/giant_bomb_api/client.rb
@@ -222,7 +249,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
222
249
  version: '0'
223
250
  requirements: []
224
251
  rubyforge_project:
225
- rubygems_version: 2.4.6
252
+ rubygems_version: 2.4.5
226
253
  signing_key:
227
254
  specification_version: 4
228
255
  summary: An unofficial ruby wrapper for the Giantbomb API (http://api.giantbomb.com).
data/Gemfile.lock DELETED
@@ -1,81 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- giant_bomb_api (0.1)
5
- activesupport
6
- faraday
7
- faraday_middleware
8
- require_all
9
-
10
- GEM
11
- remote: https://rubygems.org/
12
- specs:
13
- activesupport (4.2.4)
14
- i18n (~> 0.7)
15
- json (~> 1.7, >= 1.7.7)
16
- minitest (~> 5.1)
17
- thread_safe (~> 0.3, >= 0.3.4)
18
- tzinfo (~> 1.1)
19
- byebug (3.5.1)
20
- columnize (~> 0.8)
21
- debugger-linecache (~> 1.2)
22
- slop (~> 3.6)
23
- codeclimate-test-reporter (0.4.5)
24
- simplecov (>= 0.7.1, < 1.0.0)
25
- coderay (1.1.0)
26
- columnize (0.9.0)
27
- debugger-linecache (1.2.0)
28
- diff-lcs (1.2.5)
29
- docile (1.1.5)
30
- faraday (0.9.1)
31
- multipart-post (>= 1.2, < 3)
32
- faraday_middleware (0.10.0)
33
- faraday (>= 0.7.4, < 0.10)
34
- i18n (0.7.0)
35
- json (1.8.3)
36
- method_source (0.8.2)
37
- minitest (5.8.0)
38
- multi_json (1.10.1)
39
- multipart-post (2.0.0)
40
- pry (0.10.1)
41
- coderay (~> 1.1.0)
42
- method_source (~> 0.8.1)
43
- slop (~> 3.4)
44
- pry-byebug (3.0.1)
45
- byebug (~> 3.4)
46
- pry (~> 0.10)
47
- rake (10.1.1)
48
- require_all (1.3.2)
49
- rspec (3.1.0)
50
- rspec-core (~> 3.1.0)
51
- rspec-expectations (~> 3.1.0)
52
- rspec-mocks (~> 3.1.0)
53
- rspec-core (3.1.7)
54
- rspec-support (~> 3.1.0)
55
- rspec-expectations (3.1.2)
56
- diff-lcs (>= 1.2.0, < 2.0)
57
- rspec-support (~> 3.1.0)
58
- rspec-mocks (3.1.3)
59
- rspec-support (~> 3.1.0)
60
- rspec-support (3.1.2)
61
- simplecov (0.9.1)
62
- docile (~> 1.1.0)
63
- multi_json (~> 1.0)
64
- simplecov-html (~> 0.8.0)
65
- simplecov-html (0.8.0)
66
- slop (3.6.0)
67
- thread_safe (0.3.5)
68
- timecop (0.7.1)
69
- tzinfo (1.2.2)
70
- thread_safe (~> 0.1)
71
-
72
- PLATFORMS
73
- ruby
74
-
75
- DEPENDENCIES
76
- codeclimate-test-reporter
77
- giant_bomb_api!
78
- pry-byebug
79
- rake (~> 10.1.0)
80
- rspec (~> 3.0)
81
- timecop
data/circle.yml DELETED
@@ -1,6 +0,0 @@
1
- machine:
2
- environment:
3
- CODECLIMATE_REPO_TOKEN: "1fdcaf004abc7657d5aeb234af9f3da6419b07aaad7b78ea5d837bc9da2b78b9"
4
- timezone: "Europe/Berlin"
5
- ruby:
6
- version: "2.2.2"