bomb_defuser 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,5 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ vendor
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in bomb_defuser.gemspec
4
+ gemspec
@@ -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.
@@ -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
+
@@ -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
@@ -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,8 @@
1
+ # -*- encoding: utf-8 -*-
2
+ module BombDefuser
3
+ class Company
4
+ extend Resource
5
+
6
+ @resource = "company"
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ # -*- encoding: utf-8 -*-
2
+ module BombDefuser
3
+ class CompanyList
4
+ extend ResourceList
5
+
6
+ @resource = "companies"
7
+ end
8
+ end
@@ -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,8 @@
1
+ # -*- encoding: utf-8 -*-
2
+ module BombDefuser
3
+ class Game
4
+ extend Resource
5
+
6
+ @resource = "game"
7
+ end
8
+ 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,8 @@
1
+ # -*- encoding: utf-8 -*-
2
+ module BombDefuser
3
+ class Genre
4
+ extend Resource
5
+
6
+ @resource = "genre"
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ # -*- encoding: utf-8 -*-
2
+ module BombDefuser
3
+ class GenreList
4
+ extend ResourceList
5
+
6
+ @resource = "genres"
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ # -*- encoding: utf-8 -*-
2
+ module BombDefuser
3
+ class Platform
4
+ extend Resource
5
+
6
+ @resource = "platform"
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ # -*- encoding: utf-8 -*-
2
+ module BombDefuser
3
+ class PlatformList
4
+ extend ResourceList
5
+
6
+ @resource = "platforms"
7
+ end
8
+ 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,12 @@
1
+ # -*- encoding: utf-8 -*-
2
+ module BombDefuser
3
+ module Resource
4
+ def details(resource_id)
5
+ request = Request.new("#{resource}/#{resource_id}")
6
+ request.get
7
+ end
8
+
9
+ private
10
+ attr_accessor :resource
11
+ end
12
+ 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