luchadeer 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 77d28c953c62036e898630d204bd3e630ecc90e5
4
- data.tar.gz: 675625e43a2d925c7e1697d37ff5563a91536eb0
3
+ metadata.gz: bfbc3969949f80b2c6fe14722317f9b88cbdb31e
4
+ data.tar.gz: f1ad8f45243b83a111039bbf6dc5263f6342edb2
5
5
  SHA512:
6
- metadata.gz: 53d5e8f133ffabf11316572708618b7a937c374647b30d09ed0fd6ea142f8a99b8a2862cb4f9d8b1e27707f4f731c9ae8ad10a80ad7c76b86b72c4d28814990d
7
- data.tar.gz: dc98a568a7fb9af7c92ddcac6b99e7744f0ceae2f9c34466484c4e5d91762f893a6c1d6632a728c044ac4bc978dab654d92bc4b881d9262945d07166a918031a
6
+ metadata.gz: 769594975368dc99024b093ae1027068e8d659c43833f6d4b8e47b702959e9dcd696bbd6a483251a3b13dae49b7fbf6367f5a1934f4cc50aa145b419ca381b63
7
+ data.tar.gz: 8124aef0e0a7062d4d5ee373ab196d1a34f64381fb9cf748d228acbd432be0a816802987a08249c14cf7ebc475119131c14f6aea4020ff3ddcf288f84471edbf
data/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
  [![Coverage Status](https://coveralls.io/repos/paulfri/luchadeer/badge.png?branch=master)][coverage]
5
5
  [![Code Climate](https://codeclimate.com/github/paulfri/luchadeer.png)][grade]
6
6
 
7
- [build]: (https://travis-ci.org/paulfri/luchadeer)
7
+ [build]: https://travis-ci.org/paulfri/luchadeer
8
8
  [coverage]: https://coveralls.io/r/paulfri/luchadeer?branch=master
9
9
  [grade]: https://codeclimate.com/github/paulfri/luchadeer
10
10
 
@@ -18,16 +18,13 @@ The bombingest Giant Bomb API client library for Ruby.
18
18
  5. Thread-ready (thready?): no global or class state. Use convenience methods to use a default client per-thread, or use an alternate syntax for full control.
19
19
 
20
20
  ## Configuration
21
- Get your API key [here](http://www.giantbomb.com/api).
21
+ Get your API key [here](http://www.giantbomb.com/api). If you have a premium account, your API key should give you access to subscriber-only video resources, as well as links to HD-quality videos.
22
22
 
23
23
  ```ruby
24
24
  Luchadeer.configure(api_key: 'my_api_key') # default client for this thread
25
25
  Luchadeer::Client.new(api_key: 'my_api_key')
26
- ```
27
-
28
- You can also pass a block to either method, and it will yield the client object to configure to your liking.
29
26
 
30
- ```ruby
27
+ # You can also pass a block to either method, and it will yield the client object to configure to your liking.
31
28
  Luchadeer.configure do |client|
32
29
  client.api_key = 'my_api_key'
33
30
  end
@@ -47,12 +44,29 @@ end
47
44
  ## Usage
48
45
 
49
46
  ```ruby
47
+ # Resources
50
48
  Luchadeer::Game.find(21373) # or...
51
49
  my_client.game(21373) # => #<Luchadeer::Game name="Shin Megami Tensei: Persona 4" ...>
50
+
51
+ # Search: mix and match whatever syntax you like
52
+ Luchadeer::Search.new(page: 1, limit: 50, query: 'valkyria').fetch
53
+
54
+ search = Luchadeer::Search.new
55
+ search.page(1).limit(50).sort('name', :desc)
56
+ search.resources([Luchadeer::Game, Luchadeer::Character])
57
+ search.query('valkyria')
58
+ search.fetch
59
+
60
+ Luchadeer::Search.new { |s|
61
+ s.query = 'valkyria'
62
+ s.page = 1
63
+ s.limit = 50
64
+ }.fetch
52
65
  ```
53
66
 
54
67
  ## TODO
55
- 1. Add filtering to search.
68
+ 1. Add custom filtering to search (i.e., the 'filter' request parameter).
56
69
  2. Add per-resource searching class methods on each resource object.
57
70
  3. Refactor the test suite with shared example groups.
58
71
  4. Make the caching layer more flexible - more options besides in-memory store. Add a null store, too.
72
+ 5. Add remaining missing resources: accessory, chat, game_rating, genre, platform, promo, rating_board, region, release, review, theme, types, user_review, video_type. None of these show up in search. Refactoring is probably necessary.
@@ -12,10 +12,7 @@ module Luchadeer
12
12
  GIANT_BOMB = 'http://www.giantbomb.com/api'
13
13
 
14
14
  def initialize(opts = {})
15
- opts.each do |key, value|
16
- send(:"#{key}=", value)
17
- end
18
-
15
+ @api_key = opts[:api_key] if opts[:api_key]
19
16
  yield self if block_given?
20
17
  end
21
18
 
@@ -10,8 +10,6 @@ require 'luchadeer/video'
10
10
 
11
11
  module Luchadeer
12
12
  class Search
13
- attr_accessor :query
14
-
15
13
  RESOURCE_TYPES = {
16
14
  'character' => Luchadeer::Character,
17
15
  'company' => Luchadeer::Company,
@@ -24,8 +22,12 @@ module Luchadeer
24
22
  'video' => Luchadeer::Video
25
23
  }
26
24
 
27
- def initialize(query)
28
- @query = query
25
+ def initialize(opts = {})
26
+ opts.each do |key, value|
27
+ send(:"#{key}=", value)
28
+ end
29
+
30
+ yield self if block_given?
29
31
  end
30
32
 
31
33
  def fetch
@@ -35,10 +37,49 @@ module Luchadeer
35
37
  end.compact
36
38
  end
37
39
 
40
+ QUERY_PARAMS = [:query, :limit, :page, :fields, :resources, :sort]
41
+ attr_writer *QUERY_PARAMS
42
+
43
+ QUERY_PARAMS.each do |method|
44
+ define_method("#{method}") do |param = nil|
45
+ ivar = "@#{method.to_s}"
46
+ return instance_variable_get(ivar) unless param
47
+ instance_variable_set(ivar, param)
48
+ self
49
+ end
50
+ end
51
+
52
+ def resources(resources = nil)
53
+ return @resources unless resources
54
+ append_resources(resources)
55
+ self
56
+ end
57
+
58
+ def sort(attribute = nil, dir = :asc)
59
+ return @sort unless attribute
60
+ @sort = "#{attribute}:#{dir}"
61
+ self
62
+ end
63
+
38
64
  private
39
65
 
40
66
  def search_params
41
- { query: @query }
67
+ { query: @query, limit: @limit, resources: @resources, page: @page,
68
+ sort: @sort }.delete_if { |_, v| v.nil? }
69
+ end
70
+
71
+ def append_resources(resources)
72
+ @resources ||= ''
73
+ resources = (RESOURCE_TYPES.invert[resources] || '') if resources.is_a? Class
74
+
75
+ rx = resources.is_a?(Array) ? resources : resources.split(',')
76
+ rx.each do |r|
77
+ r = (RESOURCE_TYPES.invert[r] || '') if r.is_a? Class
78
+ RESOURCE_TYPES[r] or raise(ArgumentError, 'Invalid resource type supplied')
79
+ @resources << ",#{r}"
80
+ end
81
+
82
+ @resources.sub!(/\A,+/, '')
42
83
  end
43
84
 
44
85
  end
@@ -1,3 +1,3 @@
1
1
  module Luchadeer
2
- VERSION = '0.1.0'
2
+ VERSION = '0.2.0'
3
3
  end
@@ -2,26 +2,161 @@ require 'spec_helper'
2
2
 
3
3
  describe Luchadeer::Search do
4
4
  let(:query) { 'Chie Satonaka' }
5
+ let(:limit) { 10 }
6
+ let(:page) { 1 }
7
+ let(:sort) { 'name' }
8
+ let(:search) { described_class.new }
5
9
  let(:search_path) { %r(#{Luchadeer::Client::GIANT_BOMB}/search) }
10
+ let(:empty_body) { { body: '{ "results": [] }' } }
6
11
 
7
12
  describe '#initialize' do
8
- it 'instantiates with a search query' do
9
- expect(described_class.new(query).query).to eq query
13
+ it 'instantiates with no arguments' do
14
+ expect(described_class.new).to be_instance_of described_class
15
+ end
16
+
17
+ it 'instantiates with an options hash' do
18
+ expect(described_class.new(query: query).query).to eq query
19
+ end
20
+
21
+ it 'yields self if block given' do
22
+ expect { |b| described_class.new(&b) }.to yield_control
23
+ end
24
+ end
25
+
26
+ describe '#query' do
27
+ it 'sets the query' do
28
+ expect(search.query(query).query).to eq query
29
+ end
30
+
31
+ it 'returns the search instance' do
32
+ expect(search.query(query)).to eq search
33
+ end
34
+ end
35
+
36
+ describe '#limit' do
37
+ it 'sets the limit' do
38
+ expect(search.limit(limit).limit).to eq limit
39
+ end
40
+
41
+ it 'returns the search instance' do
42
+ expect(search.limit(limit)).to eq search
43
+ end
44
+ end
45
+
46
+ describe '#page' do
47
+ it 'sets the page' do
48
+ expect(search.page(page).page).to eq page
49
+ end
50
+
51
+ it 'returns the search instance' do
52
+ expect(search.page(page)).to eq search
53
+ end
54
+ end
55
+
56
+ describe '#sort' do
57
+ it 'sets the sort to the given parameter and defaults to ascending' do
58
+ expect(search.sort(sort).sort).to eq "#{sort}:asc"
59
+ end
60
+
61
+ it 'allows changing the sort direction' do
62
+ expect(search.sort(sort, :desc).sort).to eq "#{sort}:desc"
63
+ end
64
+
65
+ it 'allows changing the sort with a string' do
66
+ expect(search.sort(sort, 'desc').sort).to eq "#{sort}:desc"
67
+ end
68
+
69
+ it 'returns the search instance' do
70
+ expect(search.sort(sort)).to eq search
71
+ end
72
+ end
73
+
74
+ describe '#resources' do
75
+ context 'when called with a valid string' do
76
+ it 'sets resources to the given string' do
77
+ expect(search.resources('person,location').resources).to eq 'person,location'
78
+ end
79
+ end
80
+
81
+ context 'when called with an invalid string' do
82
+ it 'raises ArgumentError' do
83
+ expect { search.resources('naoto,yosuke,kanji').resources }.to raise_error ArgumentError
84
+ end
85
+ end
86
+
87
+ context 'when called with class' do
88
+ it 'maps the class to a string' do
89
+ expect(search.resources(Luchadeer::Person).resources).to eq 'person'
90
+ end
91
+ end
92
+
93
+ context 'when called with array' do
94
+ context 'of valid' do
95
+ context 'strings' do
96
+ it 'sets resources to comma-delimited string of given strings' do
97
+ expect(search.resources(['person', 'location']).resources).to eq 'person,location'
98
+ end
99
+ end
100
+
101
+ context 'classes' do
102
+ it 'maps the classes to strings' do
103
+ expect(search.resources([Luchadeer::Person, Luchadeer::Location]).resources).to eq 'person,location'
104
+ end
105
+ end
106
+ end
107
+
108
+ context 'of invalid' do
109
+ context 'strings' do
110
+ it 'raises ArgumentError' do
111
+ expect { search.resources ['person', 'naoto'] }.to raise_error ArgumentError
112
+ end
113
+ end
114
+
115
+ context 'classes' do
116
+ it 'raises ArgumentError' do
117
+ expect { search.resources [String, BasicObject, Luchadeer::Search] }.to raise_error ArgumentError
118
+ end
119
+ end
120
+ end
10
121
  end
11
122
  end
12
123
 
13
124
  describe '#fetch' do
125
+ let(:search) { described_class.new(query: query).fetch }
126
+
14
127
  before :each do
15
128
  Luchadeer.client = Luchadeer::Client.new
16
129
  end
17
130
 
18
131
  it 'queries the Giant Bomb search API' do
19
- stub = stub_request(:get, search_path).to_return(body: '{ "results": [] }')
132
+ stub = stub_request(:get, search_path).to_return(empty_body)
20
133
 
21
- described_class.new(query).fetch
134
+ search
22
135
  expect(stub).to have_been_requested
23
136
  end
24
137
 
138
+ describe 'request parameters' do
139
+ it 'includes supplied parameters' do
140
+ params = { query: query, limit: 10, page: 1, resources: 'video', sort: 'name:asc' }
141
+
142
+ stub = stub_request(:get, "http://www.giantbomb.com/api/search")
143
+ .with(query: { api_key: nil, format: 'json' }.merge(params))
144
+ .to_return(empty_body)
145
+
146
+ described_class.new(params).fetch
147
+ expect(stub).to have_been_requested
148
+ end
149
+
150
+ it 'omits nil parameters' do
151
+ stub = stub_request(:get, "http://www.giantbomb.com/api/search")
152
+ .with(query: { api_key: nil, format: 'json', query: query })
153
+ .to_return(empty_body)
154
+
155
+ described_class.new(query: query, limit: nil, page: nil).fetch
156
+ expect(stub).to have_been_requested
157
+ end
158
+ end
159
+
25
160
  describe 'generates the proper class based on the result type' do
26
161
  subject do
27
162
  stub_request(:get, search_path).to_return(body:
@@ -36,7 +171,7 @@ describe Luchadeer::Search do
36
171
  {"resource_type": "person"},
37
172
  {"resource_type": "video"}
38
173
  ] }')
39
- described_class.new(query).fetch
174
+ search
40
175
  end
41
176
 
42
177
  its([0]) { should be_instance_of Luchadeer::Character }
@@ -50,18 +185,18 @@ describe Luchadeer::Search do
50
185
  its([8]) { should be_instance_of Luchadeer::Video }
51
186
  end
52
187
 
53
- context 'when there are no results' do
54
- it 'returns an empty array' do
188
+ context 'when the resource type isn\'t mapped' do
189
+ it 'skips modeling the resource' do
55
190
  stub_request(:get, search_path).to_return(body:
56
191
  '{ "results": [{ "resource_type": "banana"}] }')
57
- expect(described_class.new(query).fetch).to eq []
192
+ expect(search).to be_empty
58
193
  end
59
194
  end
60
195
 
61
- context 'when the resource type isn\'t mapped' do
62
- it 'skips modeling the resource' do
63
- stub_request(:get, search_path).to_return(body: '{ "results": [] }')
64
- expect(described_class.new(query).fetch).to eq []
196
+ context 'when there are no results' do
197
+ it 'returns an empty array' do
198
+ stub_request(:get, search_path).to_return(empty_body)
199
+ expect(search).to be_empty
65
200
  end
66
201
  end
67
202
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: luchadeer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paul Friedman
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-02-09 00:00:00.000000000 Z
11
+ date: 2014-02-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -184,7 +184,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
184
184
  version: '0'
185
185
  requirements: []
186
186
  rubyforge_project:
187
- rubygems_version: 2.2.1
187
+ rubygems_version: 2.2.0
188
188
  signing_key:
189
189
  specification_version: 4
190
190
  summary: The bombingest Giant Bomb API client library for Ruby.