bomb_defuser 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +5 -0
- data/Gemfile +4 -0
- data/MIT-LICENSE +20 -0
- data/README.textile +105 -0
- data/Rakefile +1 -0
- data/bomb_defuser.gemspec +27 -0
- data/lib/bomb_defuser.rb +26 -0
- data/lib/bomb_defuser/company.rb +8 -0
- data/lib/bomb_defuser/company_list.rb +8 -0
- data/lib/bomb_defuser/configuration.rb +15 -0
- data/lib/bomb_defuser/curb_adapter.rb +18 -0
- data/lib/bomb_defuser/errors.rb +9 -0
- data/lib/bomb_defuser/game.rb +8 -0
- data/lib/bomb_defuser/game_list.rb +17 -0
- data/lib/bomb_defuser/genre.rb +8 -0
- data/lib/bomb_defuser/genre_list.rb +8 -0
- data/lib/bomb_defuser/platform.rb +8 -0
- data/lib/bomb_defuser/platform_list.rb +8 -0
- data/lib/bomb_defuser/request.rb +43 -0
- data/lib/bomb_defuser/resource.rb +12 -0
- data/lib/bomb_defuser/resource_list.rb +15 -0
- data/lib/bomb_defuser/response_handler.rb +57 -0
- data/lib/bomb_defuser/theme.rb +8 -0
- data/lib/bomb_defuser/theme_list.rb +8 -0
- data/lib/bomb_defuser/version.rb +3 -0
- data/spec/.rspec +2 -0
- data/spec/curb_adapter_spec.rb +25 -0
- data/spec/fixtures/resource_get_fail.json +1 -0
- data/spec/fixtures/resource_get_success.json +1 -0
- data/spec/fixtures/resource_list_get_success.json +1 -0
- data/spec/request_spec.rb +49 -0
- data/spec/resource_list_spec.rb +58 -0
- data/spec/resource_spec.rb +31 -0
- data/spec/response_handler_spec.rb +79 -0
- data/spec/spec_helper.rb +11 -0
- metadata +144 -0
data/Gemfile
ADDED
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2011 Lucas HĂșngaro
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.textile
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
h1. bomb_defuser
|
2
|
+
|
3
|
+
A simple wrapper for the awesome GiantBomb.com API.
|
4
|
+
|
5
|
+
Does bomb_defuser helps your daily work with Ruby? So, "please recommend me in Work With Rails":http://workingwithrails.com/recommendation/new/person/9370-lucas-h-ngaro and thanks for your kindness! :)
|
6
|
+
|
7
|
+
h2. How?
|
8
|
+
|
9
|
+
First, install the gem:
|
10
|
+
|
11
|
+
<pre>
|
12
|
+
$ [sudo] gem install bomb_defuser
|
13
|
+
</pre>
|
14
|
+
|
15
|
+
Then, add it as a dependency of your code using your favorite way (a simple require or mechanisms like the Bundler gem).
|
16
|
+
|
17
|
+
Using it is really simple.
|
18
|
+
|
19
|
+
First, you need an API key. Then, configure bomb_defuser to use it:
|
20
|
+
|
21
|
+
<pre>
|
22
|
+
BombDefuser::Configuration.api_key = "my api key"
|
23
|
+
</pre>
|
24
|
+
|
25
|
+
Now to the real data consumption. There are two kinds of entities: a Resource (single entity) and a ResourceList (list of entities).
|
26
|
+
|
27
|
+
An example of Resource is a Game. To get data about a particular game you can do the following:
|
28
|
+
|
29
|
+
<pre>
|
30
|
+
>> BombDefuser::Game.details(17280)
|
31
|
+
=> <#Hashie::Mash name="BioShock" ...>
|
32
|
+
</pre>
|
33
|
+
|
34
|
+
An example of a ResourceList is a GameList. To get a list of games you can do the following:
|
35
|
+
|
36
|
+
<pre>
|
37
|
+
>> BombDefuser::GameList.fetch
|
38
|
+
=> [<#Hashie::Mash name="BioShock" ...>, <#Hashie::Mash name="Civilization V" ...>, ...]
|
39
|
+
</pre>
|
40
|
+
|
41
|
+
As you can see, the gem makes use of "Hashie's":https://github.com/intridea/hashie Mash, which basically is a Hash with attribute accessors for all keys, meaning you can use the dot notation to access values:
|
42
|
+
|
43
|
+
<pre>
|
44
|
+
>> game = BombDefuser::Game.details(17280)
|
45
|
+
=> <#Hashie::Mash name="BioShock" ...>
|
46
|
+
>> game.name
|
47
|
+
=> "BioShock"
|
48
|
+
</pre>
|
49
|
+
|
50
|
+
For a Resource, the return will always be a Mash instance. For a ResourceList, it will be an Array of Mash instances.
|
51
|
+
|
52
|
+
A Resource has one method (details) which receives the entity id.
|
53
|
+
|
54
|
+
A ResourceList has one method (fetch) which receives two numeric parameters regarding pagination: the first one is the current page and the second one is the amount of elements per page.
|
55
|
+
|
56
|
+
The GameList can also send a "platforms" parameter, which is an Array containing the ids of the gaming platforms that will be used to filter the results:
|
57
|
+
|
58
|
+
<pre>
|
59
|
+
>> BombDefuser::GameList.platforms = [35, 129]
|
60
|
+
=> [35, 129]
|
61
|
+
>> BombDefuser::GameList.fetch
|
62
|
+
=> [<#Hashie::Mash name="Uncharted" ...>, <#Hashie::Mash name="God of War" ...>, ...]
|
63
|
+
</pre>
|
64
|
+
|
65
|
+
The other lists do not feature additional filters at the moment.
|
66
|
+
|
67
|
+
For further reference, please check the "official API documentation":http://api.giantbomb.com/documentation/.
|
68
|
+
|
69
|
+
h3. Available endpoints
|
70
|
+
|
71
|
+
Resources:
|
72
|
+
|
73
|
+
* Company
|
74
|
+
* Game
|
75
|
+
* Genre
|
76
|
+
* Platform
|
77
|
+
* Theme
|
78
|
+
|
79
|
+
Resource lists:
|
80
|
+
|
81
|
+
* Companies
|
82
|
+
* Games
|
83
|
+
* Genres
|
84
|
+
* Platforms
|
85
|
+
* Themes
|
86
|
+
|
87
|
+
h3. Additional configuration
|
88
|
+
|
89
|
+
Besides the API key, the Configuration class allows you to configure an adapter to make HTTP requests (you can use the included "CurbAdapter":https://github.com/lucashungaro/bomb_defuser/blob/master/lib/curb_adapter.rb. and its specs as an example of implementation) and a logger (STDOUT by default).
|
90
|
+
|
91
|
+
h2. Note on Patches/Pull Requests
|
92
|
+
|
93
|
+
* Fork the project.
|
94
|
+
* Make your feature addition or bug fix.
|
95
|
+
* Add tests for it. This is important so I don't break it in a
|
96
|
+
future version unintentionally.
|
97
|
+
* Commit, do not mess with rakefile, version, or history.
|
98
|
+
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
99
|
+
* Send me a pull request. Bonus points for topic branches.
|
100
|
+
|
101
|
+
|
102
|
+
h3. License
|
103
|
+
|
104
|
+
sentinel is released under the MIT license. See "MIT LICENSE":https://github.com/lucashungaro/bomb_defuser/blob/master/MIT-LICENSE.
|
105
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "bomb_defuser/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "bomb_defuser"
|
7
|
+
s.version = BombDefuser::VERSION
|
8
|
+
s.authors = ["Lucas HĂșngaro"]
|
9
|
+
s.email = ["lucashungaro@gmail.com"]
|
10
|
+
s.homepage = "https://github.com/lucashungaro/bomb_defuser"
|
11
|
+
s.summary = %q{A simple wrapper for the awesome GiantBomb.com API}
|
12
|
+
s.description = %q{A simple wrapper for the awesome GiantBomb.com API}
|
13
|
+
|
14
|
+
s.rubyforge_project = "bomb_defuser"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
s.add_development_dependency "rspec", "2.6"
|
22
|
+
s.add_development_dependency "webmock", "1.7.6"
|
23
|
+
|
24
|
+
s.add_runtime_dependency "curb", "0.7.15"
|
25
|
+
s.add_runtime_dependency "hashie", "1.1.0"
|
26
|
+
s.add_runtime_dependency "yajl-ruby", "0.8.3"
|
27
|
+
end
|
data/lib/bomb_defuser.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require "bomb_defuser/version"
|
3
|
+
|
4
|
+
require "bomb_defuser/curb_adapter"
|
5
|
+
require "bomb_defuser/errors"
|
6
|
+
require "bomb_defuser/request"
|
7
|
+
require "bomb_defuser/response_handler"
|
8
|
+
require "bomb_defuser/resource"
|
9
|
+
require "bomb_defuser/resource_list"
|
10
|
+
|
11
|
+
require "bomb_defuser/company"
|
12
|
+
require "bomb_defuser/company_list"
|
13
|
+
require "bomb_defuser/configuration"
|
14
|
+
require "bomb_defuser/game"
|
15
|
+
require "bomb_defuser/game_list"
|
16
|
+
require "bomb_defuser/genre"
|
17
|
+
require "bomb_defuser/genre_list"
|
18
|
+
require "bomb_defuser/platform"
|
19
|
+
require "bomb_defuser/platform_list"
|
20
|
+
require "bomb_defuser/theme"
|
21
|
+
require "bomb_defuser/theme_list"
|
22
|
+
|
23
|
+
require "curb"
|
24
|
+
require "hashie"
|
25
|
+
require "logger"
|
26
|
+
require "yajl"
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require "logger"
|
3
|
+
|
4
|
+
module BombDefuser
|
5
|
+
class Configuration
|
6
|
+
BASE_URL = "http://api.giantbomb.com"
|
7
|
+
|
8
|
+
@http_library_adapter = CurbAdapter
|
9
|
+
@logger = Logger.new(STDOUT)
|
10
|
+
|
11
|
+
class << self
|
12
|
+
attr_accessor :api_key, :http_library_adapter, :logger
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
require "ostruct"
|
3
|
+
|
4
|
+
module BombDefuser
|
5
|
+
class CurbAdapter
|
6
|
+
def self.http_get(url, headers = {})
|
7
|
+
begin
|
8
|
+
response = Curl::Easy.http_get(url) {|config| config.headers = headers }
|
9
|
+
|
10
|
+
if response
|
11
|
+
OpenStruct.new(:body => response.body_str, :code => response.response_code, :headers => response.headers)
|
12
|
+
end
|
13
|
+
rescue StandardError => e
|
14
|
+
raise Errors::WebServiceNotAvailableError, e.message
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
module BombDefuser
|
3
|
+
module Errors
|
4
|
+
class InvalidRequestError < StandardError; end
|
5
|
+
class RequestFailedError < StandardError; end
|
6
|
+
class UnrecognizedResponseError < StandardError; end
|
7
|
+
class WebServiceNotAvailableError < StandardError; end
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
module BombDefuser
|
3
|
+
class GameList
|
4
|
+
extend ResourceList
|
5
|
+
|
6
|
+
@resource = "games"
|
7
|
+
|
8
|
+
class << self
|
9
|
+
attr_accessor :platforms
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.include_additional_parameters
|
13
|
+
self.platforms ||= []
|
14
|
+
params[:platforms] = platforms.join(",") unless platforms.empty?
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
module BombDefuser
|
3
|
+
class Request
|
4
|
+
def initialize(resource, params = {})
|
5
|
+
self.request_url = "#{Configuration::BASE_URL}/#{resource}/"
|
6
|
+
self.request_params = build_params(params)
|
7
|
+
self.logger = Configuration.logger
|
8
|
+
self.http_client = Configuration.http_library_adapter
|
9
|
+
end
|
10
|
+
|
11
|
+
def get(response_handler = ResponseHandler.new)
|
12
|
+
url = build_url
|
13
|
+
logger.info("GET on #{url}")
|
14
|
+
|
15
|
+
response = http_client.http_get(url)
|
16
|
+
response_handler.process(response)
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
attr_accessor :http_client, :logger, :request_url, :request_params
|
21
|
+
|
22
|
+
def build_params(params)
|
23
|
+
building_params = {:format => "json", :api_key => Configuration.api_key}
|
24
|
+
|
25
|
+
if limit = params.delete(:per_page)
|
26
|
+
building_params[:limit] = limit
|
27
|
+
building_params[:offset] = (params.delete(:page_number) - 1) * limit
|
28
|
+
end
|
29
|
+
|
30
|
+
building_params.merge!(params)
|
31
|
+
building_params
|
32
|
+
end
|
33
|
+
|
34
|
+
def build_url
|
35
|
+
params = request_params.inject([]) do |memo, param_pair|
|
36
|
+
memo << "#{param_pair[0]}=#{param_pair[1]}"
|
37
|
+
end
|
38
|
+
|
39
|
+
building_url = request_url.dup
|
40
|
+
building_url << "?#{params.join('&')}"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
module BombDefuser
|
3
|
+
module ResourceList
|
4
|
+
def fetch(page_number = 1, per_page = 100)
|
5
|
+
self.params = {:page_number => page_number, :per_page => per_page}
|
6
|
+
include_additional_parameters
|
7
|
+
|
8
|
+
request = Request.new(resource, params)
|
9
|
+
request.get
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
attr_accessor :params, :resource
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
module BombDefuser
|
3
|
+
class ResponseHandler
|
4
|
+
def initialize(parser = Yajl::Parser.new)
|
5
|
+
self.parser = parser
|
6
|
+
self.logger = Configuration.logger
|
7
|
+
end
|
8
|
+
|
9
|
+
def process(response)
|
10
|
+
raise(Errors::UnrecognizedResponseError, "The response can't be nil") if response.nil?
|
11
|
+
|
12
|
+
parse(response, parser)
|
13
|
+
result_size > 1 ? process_collection : process_single_resource
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
attr_accessor :logger, :parser, :result_size, :results
|
18
|
+
|
19
|
+
def parse(response, parser)
|
20
|
+
if valid_response?(response)
|
21
|
+
parsed_response = parser.parse(response.body)
|
22
|
+
handle_api_details(parsed_response)
|
23
|
+
else
|
24
|
+
raise Errors::UnrecognizedResponseError, "Your request didn't return a standard response from BombDefuser's API. Please check the log."
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def valid_response?(response)
|
29
|
+
if response.code == 200
|
30
|
+
true
|
31
|
+
else
|
32
|
+
logger.info("Request failed. Http status: #{response.code}. Body: #{response.body}")
|
33
|
+
raise Errors::RequestFailedError, "The request failed with http code #{response.code}"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def handle_api_details(parsed_response)
|
38
|
+
if parsed_response["status_code"] == 1
|
39
|
+
self.result_size = parsed_response["number_of_page_results"]
|
40
|
+
self.results = parsed_response["results"]
|
41
|
+
else
|
42
|
+
logger.info("The API returned an error: #{parsed_response["error"]}")
|
43
|
+
raise Errors::InvalidRequestError, parsed_response["error"]
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def process_collection
|
48
|
+
results.inject([]) do |collection, element|
|
49
|
+
collection << Hashie::Mash.new(element)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def process_single_resource
|
54
|
+
Hashie::Mash.new(results)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|