siren_client 0.1.1 → 0.2.0
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 +4 -4
- data/.travis.yml +8 -0
- data/README.md +13 -1
- data/bin/siren_cli +1 -1
- data/lib/siren_client/action.rb +2 -1
- data/lib/siren_client/entity.rb +26 -6
- data/lib/siren_client/link.rb +2 -1
- data/lib/siren_client/version.rb +1 -1
- data/siren_client.gemspec +1 -2
- data/spec/helper/spec_helper.rb +12 -2
- data/spec/support/test_server.rb +1 -1
- data/spec/unit/action_spec.rb +4 -0
- data/spec/unit/entity_spec.rb +180 -7
- data/spec/unit/link_spec.rb +4 -0
- metadata +4 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f38d3c4581d5764d0798e4c4d3908f7404ca7cdb
|
4
|
+
data.tar.gz: 3e71628070a1391ef839335602ef778b1d1d7d94
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7edd967f314c6d036d7cfdef8889fd9953b1e0b19523343d71d0e5f1586d7f9438f44e01051aabb4e53e4d5489e6d01aca5f55196494bf89fdb4ecf5897065ec
|
7
|
+
data.tar.gz: 043795907a4f6166549f42f9776447a1566d8e7f47f1f7995e47826f500e467eee0e904fd50c7a4209241b2022bcbe353c0436cc78c5e00d658dc35c04d3d579
|
data/.travis.yml
ADDED
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# SirenClient
|
1
|
+
# SirenClient [](https://travis-ci.org/cha55son/siren_client)
|
2
2
|
|
3
3
|
A simple client for traversing Siren APIs. Not sure what Siren is? View the spec here: https://github.com/kevinswiber/siren.
|
4
4
|
|
@@ -46,6 +46,18 @@ root.entities[x] # This is an array
|
|
46
46
|
root.each do |entity|
|
47
47
|
# do something
|
48
48
|
end
|
49
|
+
# With full enumerable support entities work similarly to arrays
|
50
|
+
root.map { |entity| ... }
|
51
|
+
root.select { |entity| ... }
|
52
|
+
root.find { |entity| ... }
|
53
|
+
# You can view all the enumerable methods here: http://ruby-doc.org/core-2.0.0/Enumerable.html
|
54
|
+
```
|
55
|
+
|
56
|
+
Entities also provide the method `.search` for searching across sub-entities' classes, rels, and hrefs (sub-links only).
|
57
|
+
|
58
|
+
```ruby
|
59
|
+
root.search("messages") # => Array<SirenClient::Entity>
|
60
|
+
root.search(/(messages|concepts)/) # => Array<SirenClient::Entity>
|
49
61
|
```
|
50
62
|
|
51
63
|
#### Entity sub-links
|
data/bin/siren_cli
CHANGED
data/lib/siren_client/action.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
module SirenClient
|
2
2
|
class Action
|
3
|
-
|
3
|
+
attr_accessor :href
|
4
|
+
attr_reader :payload, :name, :classes, :method, :title, :type, :fields, :config
|
4
5
|
|
5
6
|
def initialize(data, config={})
|
6
7
|
if data.class != Hash
|
data/lib/siren_client/entity.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
module SirenClient
|
2
2
|
class Entity
|
3
|
+
include Enumerable
|
4
|
+
attr_accessor :href
|
3
5
|
attr_reader :payload, :classes, :properties, :entities, :rels,
|
4
|
-
:links, :actions, :title, :type, :config
|
6
|
+
:links, :actions, :title, :type, :config
|
5
7
|
|
6
8
|
|
7
9
|
def initialize(data, config={})
|
@@ -36,6 +38,23 @@ module SirenClient
|
|
36
38
|
@entities.each(&block) rescue nil
|
37
39
|
end
|
38
40
|
|
41
|
+
def search(criteria)
|
42
|
+
return false unless criteria
|
43
|
+
if criteria.is_a? String
|
44
|
+
return entities.select do |ent|
|
45
|
+
true if ent.classes.include?(criteria) ||
|
46
|
+
ent.rels.include?(criteria) ||
|
47
|
+
ent.href == criteria
|
48
|
+
end
|
49
|
+
elsif criteria.is_a? Regexp
|
50
|
+
return entities.select do |ent|
|
51
|
+
true if ent.classes.any? { |klass| criteria.match(klass) } ||
|
52
|
+
ent.rels.any? { |rel| criteria.match(rel) } ||
|
53
|
+
criteria.match(ent.href)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
39
58
|
### Entity sub-links only
|
40
59
|
def go
|
41
60
|
return if self.href.empty?
|
@@ -51,15 +70,16 @@ module SirenClient
|
|
51
70
|
end
|
52
71
|
# Does it match an entity sub-link's class?
|
53
72
|
@entities.each do |ent|
|
54
|
-
return ent.go if ent.href &&
|
73
|
+
return ent.go if ent.href &&
|
74
|
+
(ent.classes.map { |c| c.underscore }).include?(method_str.underscore)
|
55
75
|
end
|
56
76
|
# Does it match a link, if so traverse it and return the entity.
|
57
77
|
@links.each do |key, link|
|
58
|
-
return link.go if method_str == key
|
78
|
+
return link.go if method_str == key.underscore
|
59
79
|
end
|
60
80
|
# Does it match an action, if so return the action.
|
61
81
|
@actions.each do |key, action|
|
62
|
-
return action if method_str == key
|
82
|
+
return action if method_str == key.underscore
|
63
83
|
end
|
64
84
|
raise NoMethodError, 'The method does not match a property, action, or link on SirenClient::Entity.'
|
65
85
|
end
|
@@ -90,7 +110,7 @@ module SirenClient
|
|
90
110
|
hash_rel = rel and break
|
91
111
|
end
|
92
112
|
# Ensure the rel name is a valid hash key
|
93
|
-
hash[hash_rel
|
113
|
+
hash[hash_rel] = link
|
94
114
|
hash
|
95
115
|
end
|
96
116
|
@actions = @payload['actions'] || []
|
@@ -100,7 +120,7 @@ module SirenClient
|
|
100
120
|
# Convert actions into a hash
|
101
121
|
@actions = @actions.inject({}) do |hash, action|
|
102
122
|
next unless action.name
|
103
|
-
hash[action.name
|
123
|
+
hash[action.name] = action
|
104
124
|
hash
|
105
125
|
end
|
106
126
|
@title = @payload['title'] || ''
|
data/lib/siren_client/link.rb
CHANGED
data/lib/siren_client/version.rb
CHANGED
data/siren_client.gemspec
CHANGED
@@ -24,9 +24,8 @@ Gem::Specification.new do |spec|
|
|
24
24
|
spec.add_development_dependency "rack"
|
25
25
|
spec.add_development_dependency "rake"
|
26
26
|
spec.add_development_dependency "sinatra"
|
27
|
-
spec.add_development_dependency "sinatra-simple-auth"
|
28
27
|
spec.add_development_dependency "rspec"
|
29
|
-
spec.add_development_dependency "byebug"
|
28
|
+
spec.add_development_dependency "byebug" if RUBY_VERSION > "2"
|
30
29
|
spec.add_development_dependency "guard"
|
31
30
|
spec.add_development_dependency "guard-rspec"
|
32
31
|
end
|
data/spec/helper/spec_helper.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require 'byebug'
|
1
|
+
require 'byebug' if RUBY_VERSION > '2'
|
2
2
|
require 'siren_client'
|
3
3
|
|
4
4
|
RSpec.configure do |config|
|
@@ -32,6 +32,12 @@ def siren_body
|
|
32
32
|
'class' => ['concepts', 'collection'],
|
33
33
|
'rel' => ['/rels/concepts'],
|
34
34
|
'href' => '/graphs/test2/concepts'
|
35
|
+
},
|
36
|
+
{
|
37
|
+
# Just to test the underscore transformation
|
38
|
+
'class' => ['user-preferences', 'collection'],
|
39
|
+
'rel' => ['/rels/user-preferences'],
|
40
|
+
'href' => '/graphs/user/preferences'
|
35
41
|
}
|
36
42
|
],
|
37
43
|
'links' => [
|
@@ -71,7 +77,7 @@ def siren_body
|
|
71
77
|
]
|
72
78
|
},
|
73
79
|
{
|
74
|
-
'name' => '
|
80
|
+
'name' => 'filter-messages',
|
75
81
|
'method' => 'GET',
|
76
82
|
'href' => '/graphs/test1/messages',
|
77
83
|
'title' => 'Get an optionally filtered list of Messages',
|
@@ -103,6 +109,10 @@ def siren_body
|
|
103
109
|
'rel' => ['self'],
|
104
110
|
'href' => '/graphs?limit=1&page=1&order_by=name'
|
105
111
|
},
|
112
|
+
{
|
113
|
+
'rel' => ['prev-page'],
|
114
|
+
'href' => '/graphs?limit=1&page=0&order_by=name'
|
115
|
+
},
|
106
116
|
{
|
107
117
|
'rel' => ['next'],
|
108
118
|
'href' => '/graphs?limit=1&page=2&order_by=name'
|
data/spec/support/test_server.rb
CHANGED
data/spec/unit/action_spec.rb
CHANGED
@@ -52,6 +52,10 @@ describe SirenClient::Action do
|
|
52
52
|
it 'is a string' do
|
53
53
|
expect(action.href).to be_a String
|
54
54
|
end
|
55
|
+
it 'can change .href as needed' do
|
56
|
+
action.href = action.href + '?query=test'
|
57
|
+
expect(/query=test/).to match(action.href)
|
58
|
+
end
|
55
59
|
end
|
56
60
|
describe '.title' do
|
57
61
|
it 'is a string' do
|
data/spec/unit/entity_spec.rb
CHANGED
@@ -112,6 +112,10 @@ describe SirenClient::Entity do
|
|
112
112
|
it 'should be empty' do
|
113
113
|
expect(entity.href).to eq('')
|
114
114
|
end
|
115
|
+
it 'can change .href as needed' do
|
116
|
+
entity.href = 'http://example.com?query=test'
|
117
|
+
expect(/query=test/).to match(entity.href)
|
118
|
+
end
|
115
119
|
end
|
116
120
|
# Similar to SirenClient::Link.go this function will create a
|
117
121
|
# new entity from the .href method. For entity sub-links only.
|
@@ -167,13 +171,182 @@ describe SirenClient::Entity do
|
|
167
171
|
expect(entity[0]).to be_a SirenClient::Entity
|
168
172
|
end
|
169
173
|
end
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
174
|
+
let (:graph) { entity[0] }
|
175
|
+
describe '.search("messages")' do
|
176
|
+
it 'returns an Array' do
|
177
|
+
expect(graph.search('messages')).to be_a Array
|
178
|
+
end
|
179
|
+
it 'returns an Array of the right size' do
|
180
|
+
expect(graph.search('messages').length).to eq(1)
|
181
|
+
end
|
182
|
+
it 'the first element is a SirenClient::Entity' do
|
183
|
+
expect(graph.search('messages')[0]).to be_a SirenClient::Entity
|
184
|
+
end
|
185
|
+
it 'the first element\'s classes include "messages"' do
|
186
|
+
expect(graph.search('messages')[0].classes.include?('messages')).to eq(true)
|
187
|
+
end
|
188
|
+
end
|
189
|
+
describe '.string(/test1/)' do
|
190
|
+
it 'returns an Array' do
|
191
|
+
expect(graph.search(/test1/)).to be_a Array
|
192
|
+
end
|
193
|
+
it 'returns an Array of the right size' do
|
194
|
+
expect(graph.search(/test1/).length).to eq(1)
|
195
|
+
end
|
196
|
+
it 'the second element is a SirenClient::Entity' do
|
197
|
+
expect(graph.search(/test1/)[0]).to be_a SirenClient::Entity
|
198
|
+
end
|
199
|
+
it 'the second element\'s classes include "concepts"' do
|
200
|
+
expect(graph.search(/test1/)[0].classes.include?('messages')).to eq(true)
|
201
|
+
end
|
202
|
+
end
|
203
|
+
describe '.string(/test[0-9]/)' do
|
204
|
+
it 'returns an Array' do
|
205
|
+
expect(graph.search(/test[0-9]/)).to be_a Array
|
206
|
+
end
|
207
|
+
it 'returns an Array of the right size' do
|
208
|
+
expect(graph.search(/test[0-9]/).length).to eq(2)
|
209
|
+
end
|
210
|
+
it 'the second element is a SirenClient::Entity' do
|
211
|
+
expect(graph.search(/test[0-9]/)[1]).to be_a SirenClient::Entity
|
212
|
+
end
|
213
|
+
it 'the second element\'s classes include "concepts"' do
|
214
|
+
expect(graph.search(/test[0-9]/)[1].classes.include?('concepts')).to eq(true)
|
215
|
+
end
|
216
|
+
end
|
217
|
+
describe 'underscore support' do
|
218
|
+
it 'can access entity sub-links' do
|
219
|
+
# Since this will trigger the sub-link. We expect an error
|
220
|
+
expect { graph.user_preferences }.to raise_error
|
221
|
+
end
|
222
|
+
it 'can access actions' do
|
223
|
+
expect(entity.filter_messages).to be_a SirenClient::Action
|
224
|
+
end
|
225
|
+
it 'can access links' do
|
226
|
+
# Since this will trigger the link. We expect an error
|
227
|
+
expect { entity.prev_page }.to raise_error
|
228
|
+
end
|
229
|
+
end
|
230
|
+
# Entities enumerable support
|
231
|
+
describe "enumerable support" do
|
232
|
+
describe '.each' do
|
233
|
+
it 'can iterate over all the entities' do
|
234
|
+
expect {
|
235
|
+
graph.each do |ent|
|
236
|
+
expect(ent).to be_a SirenClient::Entity
|
237
|
+
end
|
238
|
+
}.to_not raise_error
|
239
|
+
end
|
240
|
+
end
|
241
|
+
# Useful enumerable methods
|
242
|
+
describe '.all?' do
|
243
|
+
it 'matches .entities.all?' do
|
244
|
+
expect(
|
245
|
+
graph.all? do |ent|
|
246
|
+
ent == SirenClient::Entity
|
247
|
+
end
|
248
|
+
).to eq(
|
249
|
+
graph.entities.all? do |ent|
|
250
|
+
ent == SirenClient::Entity
|
251
|
+
end
|
252
|
+
)
|
253
|
+
end
|
254
|
+
end
|
255
|
+
describe '.find' do
|
256
|
+
it 'matches .entities.find' do
|
257
|
+
expect(
|
258
|
+
graph.find do |ent|
|
259
|
+
ent.rels.include?('/rels/messages')
|
260
|
+
end
|
261
|
+
).to eq(
|
262
|
+
graph.entities.find do |ent|
|
263
|
+
ent.rels.include?('/rels/messages')
|
264
|
+
end
|
265
|
+
)
|
266
|
+
end
|
267
|
+
end
|
268
|
+
describe '.find_all' do
|
269
|
+
it 'matches .entities.find_all' do
|
270
|
+
expect(
|
271
|
+
graph.find_all do |ent|
|
272
|
+
ent.classes.include?('collection')
|
273
|
+
end
|
274
|
+
).to eq(
|
275
|
+
graph.entities.find_all do |ent|
|
276
|
+
ent.classes.include?('collection')
|
277
|
+
end
|
278
|
+
)
|
279
|
+
end
|
280
|
+
end
|
281
|
+
describe '.first' do
|
282
|
+
it 'matches .entities.first' do
|
283
|
+
expect(graph.first).to eq(graph.entities.first)
|
284
|
+
end
|
285
|
+
end
|
286
|
+
describe '.grep' do
|
287
|
+
it "matches .entities.grep" do
|
288
|
+
expect(
|
289
|
+
graph.grep(/test1/) do |ent|
|
290
|
+
ent.href
|
291
|
+
end
|
292
|
+
).to eq(
|
293
|
+
graph.entities.grep(/test1/) do |ent|
|
294
|
+
ent.href
|
295
|
+
end
|
296
|
+
)
|
297
|
+
end
|
298
|
+
end
|
299
|
+
describe '.map' do
|
300
|
+
it 'matches .entities.map' do
|
301
|
+
expect(
|
302
|
+
graph.map do |ent|
|
303
|
+
ent.classes.include?('concepts')
|
304
|
+
end
|
305
|
+
).to eq(
|
306
|
+
graph.entities.map do |ent|
|
307
|
+
ent.classes.include?('concepts')
|
308
|
+
end
|
309
|
+
)
|
310
|
+
end
|
311
|
+
end
|
312
|
+
describe '.reject' do
|
313
|
+
it 'matches .entities.reject' do
|
314
|
+
expect(
|
315
|
+
graph.reject do |ent|
|
316
|
+
ent.classes.include?('messages')
|
317
|
+
end
|
318
|
+
).to eq(
|
319
|
+
graph.entities.reject do |ent|
|
320
|
+
ent.classes.include?('messages')
|
321
|
+
end
|
322
|
+
)
|
323
|
+
end
|
324
|
+
end
|
325
|
+
describe '.select' do
|
326
|
+
it 'matches .entities.select' do
|
327
|
+
expect(
|
328
|
+
graph.select do |ent|
|
329
|
+
ent.rels.include?('/rels/concepts')
|
330
|
+
end
|
331
|
+
).to eq(
|
332
|
+
graph.entities.select do |ent|
|
333
|
+
ent.rels.include?('/rels/concepts')
|
334
|
+
end
|
335
|
+
)
|
336
|
+
end
|
337
|
+
end
|
338
|
+
describe '.sort' do
|
339
|
+
it 'matches .entities.sort' do
|
340
|
+
expect(
|
341
|
+
graph.sort do |ent_a, ent_b|
|
342
|
+
ent_b.classes[0] <=> ent_a.classes[0]
|
343
|
+
end
|
344
|
+
).to eq(
|
345
|
+
graph.entities.sort do |ent_a, ent_b|
|
346
|
+
ent_b.classes[0] <=> ent_a.classes[0]
|
347
|
+
end
|
348
|
+
)
|
349
|
+
end
|
177
350
|
end
|
178
351
|
end
|
179
352
|
end
|
data/spec/unit/link_spec.rb
CHANGED
@@ -33,6 +33,10 @@ describe SirenClient::Link do
|
|
33
33
|
it 'is a string' do
|
34
34
|
expect(link.href).to be_a String
|
35
35
|
end
|
36
|
+
it 'can change .href as needed' do
|
37
|
+
link.href = link.href + '?query=test'
|
38
|
+
expect(/query=test/).to match(link.href)
|
39
|
+
end
|
36
40
|
end
|
37
41
|
describe '.title' do
|
38
42
|
it 'is a string' do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: siren_client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chason Choate
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-02-
|
11
|
+
date: 2015-02-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: httparty
|
@@ -94,20 +94,6 @@ dependencies:
|
|
94
94
|
- - ">="
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0'
|
97
|
-
- !ruby/object:Gem::Dependency
|
98
|
-
name: sinatra-simple-auth
|
99
|
-
requirement: !ruby/object:Gem::Requirement
|
100
|
-
requirements:
|
101
|
-
- - ">="
|
102
|
-
- !ruby/object:Gem::Version
|
103
|
-
version: '0'
|
104
|
-
type: :development
|
105
|
-
prerelease: false
|
106
|
-
version_requirements: !ruby/object:Gem::Requirement
|
107
|
-
requirements:
|
108
|
-
- - ">="
|
109
|
-
- !ruby/object:Gem::Version
|
110
|
-
version: '0'
|
111
97
|
- !ruby/object:Gem::Dependency
|
112
98
|
name: rspec
|
113
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -173,6 +159,7 @@ extra_rdoc_files: []
|
|
173
159
|
files:
|
174
160
|
- ".gitignore"
|
175
161
|
- ".rspec"
|
162
|
+
- ".travis.yml"
|
176
163
|
- Gemfile
|
177
164
|
- Guardfile
|
178
165
|
- LICENSE.txt
|
@@ -222,7 +209,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
222
209
|
version: '0'
|
223
210
|
requirements: []
|
224
211
|
rubyforge_project:
|
225
|
-
rubygems_version: 2.
|
212
|
+
rubygems_version: 2.2.2
|
226
213
|
signing_key:
|
227
214
|
specification_version: 4
|
228
215
|
summary: A client to traverse Siren APIs https://github.com/kevinswiber/siren
|