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 +4 -4
- data/README.md +21 -7
- data/lib/luchadeer/client.rb +1 -4
- data/lib/luchadeer/search.rb +46 -5
- data/lib/luchadeer/version.rb +1 -1
- data/spec/luchadeer/search_spec.rb +147 -12
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bfbc3969949f80b2c6fe14722317f9b88cbdb31e
|
4
|
+
data.tar.gz: f1ad8f45243b83a111039bbf6dc5263f6342edb2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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]:
|
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
|
-
|
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.
|
data/lib/luchadeer/client.rb
CHANGED
data/lib/luchadeer/search.rb
CHANGED
@@ -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(
|
28
|
-
|
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
|
data/lib/luchadeer/version.rb
CHANGED
@@ -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
|
9
|
-
expect(described_class.new
|
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(
|
132
|
+
stub = stub_request(:get, search_path).to_return(empty_body)
|
20
133
|
|
21
|
-
|
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
|
-
|
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
|
54
|
-
it '
|
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(
|
192
|
+
expect(search).to be_empty
|
58
193
|
end
|
59
194
|
end
|
60
195
|
|
61
|
-
context 'when
|
62
|
-
it '
|
63
|
-
stub_request(:get, search_path).to_return(
|
64
|
-
expect(
|
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.
|
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-
|
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.
|
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.
|