siren_client 0.2.1 → 0.3.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/README.md +32 -0
- data/lib/siren_client.rb +2 -0
- data/lib/siren_client/action.rb +11 -3
- data/lib/siren_client/entity.rb +43 -9
- data/lib/siren_client/link.rb +9 -1
- data/lib/siren_client/modules/with_raw_response.rb +28 -0
- data/lib/siren_client/raw_response.rb +26 -0
- data/lib/siren_client/version.rb +1 -1
- data/spec/live/traverse_spec.rb +42 -0
- data/spec/support/endpoints/root.rb +6 -0
- data/spec/unit/entity_spec.rb +13 -0
- data/spec/unit/raw_response.rb +0 -0
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1d38e18a3d8e7b27a74a1bf4e39a87de411eba9b
|
4
|
+
data.tar.gz: 533cc402ef1239c82ccdac742caaaf9fb0dff276
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bc1e058531f13b91a3f043861407bda4a978a55566650a4f00f7de1043b2db8f9f150aba0c0852a47eae4caff867ac6da1888b39491c64fc638cd7e24ab58dd8
|
7
|
+
data.tar.gz: ee8785bd0cc1ee33529aebe40d2dea9eeee3b84635fb2623935033752296a889f50ac55750c0a5f4c523ef0a95249079867abbd21a7b1a9dedc73980be31a405
|
data/README.md
CHANGED
@@ -99,6 +99,38 @@ action.fields.each do |field|
|
|
99
99
|
end
|
100
100
|
```
|
101
101
|
|
102
|
+
## Accessing the raw response
|
103
|
+
|
104
|
+
SirenClient can give you the raw response if needed. Some scenarios where this is useful:
|
105
|
+
|
106
|
+
* When the API doesn't return a siren JSON structure.
|
107
|
+
* Verifying response headers, status code, etc
|
108
|
+
|
109
|
+
You can access the raw response with the following examples:
|
110
|
+
|
111
|
+
```ruby
|
112
|
+
root = SirentClient.get(...)
|
113
|
+
|
114
|
+
# For sub-entities i.e. one named `test_concepts`
|
115
|
+
root.with_raw_response.test_concepts
|
116
|
+
|
117
|
+
# For links
|
118
|
+
root.with_raw_response.concepts
|
119
|
+
|
120
|
+
# For actions (this is different from the others)
|
121
|
+
root.filter_concepts.with_raw_response.where(...)
|
122
|
+
```
|
123
|
+
|
124
|
+
Once you get the raw response instance you can call the following functions:
|
125
|
+
|
126
|
+
```ruby
|
127
|
+
raw.class == SirenClient::RawResponse
|
128
|
+
raw.body # Returns the raw body of the response
|
129
|
+
raw.code # Returns the HTTP status code
|
130
|
+
raw.message # Returns the HTTP message i.e. "OK"
|
131
|
+
raw.headers # A hash of the headers in the response
|
132
|
+
```
|
133
|
+
|
102
134
|
## Development
|
103
135
|
|
104
136
|
Run the following commands to start development:
|
data/lib/siren_client.rb
CHANGED
data/lib/siren_client/action.rb
CHANGED
@@ -1,9 +1,12 @@
|
|
1
1
|
module SirenClient
|
2
2
|
class Action
|
3
|
+
include Modules::WithRawResponse
|
4
|
+
|
3
5
|
attr_accessor :href
|
4
6
|
attr_reader :payload, :name, :classes, :method, :title, :type, :fields, :config
|
5
7
|
|
6
8
|
def initialize(data, config={})
|
9
|
+
super()
|
7
10
|
if data.class != Hash
|
8
11
|
raise ArgumentError, "You must pass in a Hash to SirenClient::Action.new"
|
9
12
|
end
|
@@ -17,8 +20,8 @@ module SirenClient
|
|
17
20
|
@title = @payload['title'] || ''
|
18
21
|
@type = @payload['type'] || 'application/x-www-form-urlencoded'
|
19
22
|
@fields = @payload['fields'] || []
|
20
|
-
@fields.map! do |
|
21
|
-
SirenClient::Field.new(
|
23
|
+
@fields.map! do |field_data|
|
24
|
+
SirenClient::Field.new(field_data)
|
22
25
|
end
|
23
26
|
end
|
24
27
|
|
@@ -37,7 +40,12 @@ module SirenClient
|
|
37
40
|
SirenClient.logger.debug " #{k}: #{v}"
|
38
41
|
end
|
39
42
|
SirenClient.logger.debug ' ' + options[:body].to_query unless options[:body].empty?
|
40
|
-
|
43
|
+
if next_response_is_raw?
|
44
|
+
disable_raw_response
|
45
|
+
generate_raw_response(self.href, @config)
|
46
|
+
else
|
47
|
+
Entity.new(HTTParty.send(@method.to_sym, @href, options).parsed_response, @config)
|
48
|
+
end
|
41
49
|
rescue URI::InvalidURIError => e
|
42
50
|
raise InvalidURIError, e.message
|
43
51
|
rescue JSON::ParserError => e
|
data/lib/siren_client/entity.rb
CHANGED
@@ -1,16 +1,19 @@
|
|
1
1
|
module SirenClient
|
2
2
|
class Entity
|
3
3
|
include Enumerable
|
4
|
+
include Modules::WithRawResponse
|
5
|
+
|
4
6
|
attr_accessor :href
|
5
7
|
attr_reader :payload, :classes, :properties, :entities, :rels,
|
6
8
|
:links, :actions, :title, :type, :config
|
7
9
|
|
8
10
|
|
9
11
|
def initialize(data, config={})
|
12
|
+
super()
|
10
13
|
@config = { format: :json }.merge config
|
11
14
|
if data.class == String
|
12
15
|
unless data.class == String && data.length > 0
|
13
|
-
|
16
|
+
raise InvalidURIError, 'An invalid url was passed to SirenClient::Entity.new.'
|
14
17
|
end
|
15
18
|
begin
|
16
19
|
SirenClient.logger.debug "GET #{data}"
|
@@ -21,9 +24,9 @@ module SirenClient
|
|
21
24
|
raise InvalidResponseError, e.message
|
22
25
|
end
|
23
26
|
elsif data.class == Hash
|
24
|
-
|
27
|
+
@payload = data
|
25
28
|
else
|
26
|
-
|
29
|
+
raise ArgumentError, "You must pass in either a url(String) or an entity(Hash) to SirenClient::Entity.new"
|
27
30
|
end
|
28
31
|
parse_data
|
29
32
|
end
|
@@ -31,7 +34,16 @@ module SirenClient
|
|
31
34
|
# Execute an entity sub-link if called directly
|
32
35
|
# otherwise just return the entity.
|
33
36
|
def [](i)
|
34
|
-
@entities[i].href.empty?
|
37
|
+
if @entities[i].href.empty?
|
38
|
+
@entities[i]
|
39
|
+
else
|
40
|
+
if next_response_is_raw?
|
41
|
+
disable_raw_response
|
42
|
+
@entities[i].with_raw_response.go
|
43
|
+
else
|
44
|
+
@entities[i].go
|
45
|
+
end
|
46
|
+
end
|
35
47
|
end
|
36
48
|
|
37
49
|
def each(&block)
|
@@ -58,7 +70,12 @@ module SirenClient
|
|
58
70
|
### Entity sub-links only
|
59
71
|
def go
|
60
72
|
return if self.href.empty?
|
61
|
-
|
73
|
+
if next_response_is_raw?
|
74
|
+
disable_raw_response
|
75
|
+
generate_raw_response(self.href, @config)
|
76
|
+
else
|
77
|
+
self.class.new(self.href, @config)
|
78
|
+
end
|
62
79
|
end
|
63
80
|
|
64
81
|
def method_missing(method, *args)
|
@@ -70,22 +87,39 @@ module SirenClient
|
|
70
87
|
end
|
71
88
|
# Does it match an entity sub-link's class?
|
72
89
|
@entities.each do |ent|
|
73
|
-
|
74
|
-
|
90
|
+
if ent.href && (ent.classes.map { |c| underscore_name c }).include?(underscore_name(method_str))
|
91
|
+
if next_response_is_raw?
|
92
|
+
disable_raw_response
|
93
|
+
return ent.with_raw_response.go
|
94
|
+
else
|
95
|
+
return ent.go
|
96
|
+
end
|
97
|
+
end
|
75
98
|
end
|
76
99
|
# Does it match a link, if so traverse it and return the entity.
|
77
100
|
@links.each do |key, link|
|
78
|
-
|
101
|
+
if method_str == underscore_name(key)
|
102
|
+
if next_response_is_raw?
|
103
|
+
disable_raw_response
|
104
|
+
return link.with_raw_response.go
|
105
|
+
else
|
106
|
+
return link.go
|
107
|
+
end
|
108
|
+
end
|
79
109
|
end
|
80
110
|
# Does it match an action, if so return the action.
|
81
111
|
@actions.each do |key, action|
|
82
|
-
return action if method_str == key
|
112
|
+
return action if method_str == underscore_name(key)
|
83
113
|
end
|
84
114
|
raise NoMethodError, "The method \"#{method_str}\" does not match a property, action, or link on SirenClient::Entity."
|
85
115
|
end
|
86
116
|
|
87
117
|
private
|
88
118
|
|
119
|
+
def underscore_name(str)
|
120
|
+
str.underscore.gsub(' ', '_')
|
121
|
+
end
|
122
|
+
|
89
123
|
def parse_data
|
90
124
|
return if @payload.nil?
|
91
125
|
@classes = @payload['class'] || []
|
data/lib/siren_client/link.rb
CHANGED
@@ -1,9 +1,12 @@
|
|
1
1
|
module SirenClient
|
2
2
|
class Link
|
3
|
+
include Modules::WithRawResponse
|
4
|
+
|
3
5
|
attr_accessor :href
|
4
6
|
attr_reader :payload, :rels, :title, :type, :config
|
5
7
|
|
6
8
|
def initialize(data, config={})
|
9
|
+
super()
|
7
10
|
if data.class != Hash
|
8
11
|
raise ArgumentError, "You must pass in a Hash to SirenClient::Link.new"
|
9
12
|
end
|
@@ -17,7 +20,12 @@ module SirenClient
|
|
17
20
|
end
|
18
21
|
|
19
22
|
def go
|
20
|
-
|
23
|
+
if next_response_is_raw?
|
24
|
+
disable_raw_response
|
25
|
+
generate_raw_response(self.href, @config)
|
26
|
+
else
|
27
|
+
Entity.new(self.href, @config)
|
28
|
+
end
|
21
29
|
end
|
22
30
|
end
|
23
31
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module SirenClient
|
2
|
+
module Modules
|
3
|
+
module WithRawResponse
|
4
|
+
def initialize
|
5
|
+
@_next_response_is_raw = false
|
6
|
+
end
|
7
|
+
|
8
|
+
def with_raw_response
|
9
|
+
@_next_response_is_raw = true
|
10
|
+
self
|
11
|
+
end
|
12
|
+
|
13
|
+
def disable_raw_response
|
14
|
+
@_next_response_is_raw = false
|
15
|
+
end
|
16
|
+
|
17
|
+
def next_response_is_raw?
|
18
|
+
@_next_response_is_raw
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def generate_raw_response(url, config)
|
24
|
+
RawResponse.new HTTParty.get(url, config)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module SirenClient
|
2
|
+
class RawResponse
|
3
|
+
def initialize(http_res)
|
4
|
+
unless http_res.class == HTTParty::Response
|
5
|
+
raise InvalidResponseError, "SirenClient::RawResponse expects a HTTParty::Response instance."
|
6
|
+
end
|
7
|
+
@response = http_res
|
8
|
+
end
|
9
|
+
|
10
|
+
def body
|
11
|
+
@response.body
|
12
|
+
end
|
13
|
+
|
14
|
+
def code
|
15
|
+
@response.code
|
16
|
+
end
|
17
|
+
|
18
|
+
def message
|
19
|
+
@response.message.strip
|
20
|
+
end
|
21
|
+
|
22
|
+
def headers
|
23
|
+
@response.headers
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/siren_client/version.rb
CHANGED
data/spec/live/traverse_spec.rb
CHANGED
@@ -62,6 +62,9 @@ describe SirenClient do
|
|
62
62
|
expect(client.concepts).to be_a SirenClient::Entity
|
63
63
|
expect(client.concepts.links['self'].href).to eq(URL + '/concepts')
|
64
64
|
end
|
65
|
+
it 'to follow the link with spaces' do
|
66
|
+
expect(client.concepts_with_spaces).to be_a SirenClient::Entity
|
67
|
+
end
|
65
68
|
end
|
66
69
|
context 'when accessing an action with GET' do
|
67
70
|
it 'to return an action' do
|
@@ -81,6 +84,9 @@ describe SirenClient do
|
|
81
84
|
it 'to return an action' do
|
82
85
|
expect(client.filter_concepts_post).to be_a SirenClient::Action
|
83
86
|
end
|
87
|
+
it 'to return an action with spaces' do
|
88
|
+
expect(client.filter_concepts_post_with_spaces).to be_a SirenClient::Action
|
89
|
+
end
|
84
90
|
context 'with .where' do
|
85
91
|
it 'to execute the action' do
|
86
92
|
params = { search: 'obama' }
|
@@ -98,4 +104,40 @@ describe SirenClient do
|
|
98
104
|
expect(concepts).to be_a SirenClient::Entity
|
99
105
|
end
|
100
106
|
end
|
107
|
+
context 'when accessing the raw response' do
|
108
|
+
context 'links' do
|
109
|
+
it 'to return a RawResponse instance' do
|
110
|
+
expect(client.with_raw_response.concepts).to be_a SirenClient::RawResponse
|
111
|
+
end
|
112
|
+
it 'to return an Entity on the second request' do
|
113
|
+
client.with_raw_response.concepts
|
114
|
+
expect(client.concepts).to be_a SirenClient::Entity
|
115
|
+
end
|
116
|
+
end
|
117
|
+
context 'actions' do
|
118
|
+
params = { search: 'obama' }
|
119
|
+
it 'to return a RawResponse instance' do
|
120
|
+
expect(client.filter_concepts_get.with_raw_response.where(params)).to be_a SirenClient::RawResponse
|
121
|
+
end
|
122
|
+
it 'to return an Entity on the second request' do
|
123
|
+
client.filter_concepts_get.with_raw_response.where(params)
|
124
|
+
expect(client.concepts).to be_a SirenClient::Entity
|
125
|
+
end
|
126
|
+
end
|
127
|
+
it 'to provide the raw body' do
|
128
|
+
expect(client.with_raw_response.concepts.body).to eq(HTTParty.get(URL + '/concepts', basic_auth: { username: 'admin', password: '1234' }).body)
|
129
|
+
end
|
130
|
+
it 'to provide the raw status code' do
|
131
|
+
expect(client.with_raw_response.concepts.code).to eq(200)
|
132
|
+
end
|
133
|
+
it 'to provide the raw message' do
|
134
|
+
expect(client.with_raw_response.concepts.message).to eq("OK")
|
135
|
+
end
|
136
|
+
it 'to provide the raw headers' do
|
137
|
+
expect(client.with_raw_response.concepts.headers).to include(
|
138
|
+
"content-type", "content-length", "server", "date", "connection"
|
139
|
+
)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
101
143
|
end
|
@@ -16,6 +16,11 @@ class TestServer < Sinatra::Base
|
|
16
16
|
"href":"#{@@url}/concepts",
|
17
17
|
"title": "Concepts"
|
18
18
|
},
|
19
|
+
{
|
20
|
+
"rel": ["collection", "concepts with spaces"],
|
21
|
+
"href":"#{@@url}/concepts",
|
22
|
+
"title": "Concepts"
|
23
|
+
},
|
19
24
|
{ "rel": ["messages", "collection"],
|
20
25
|
"href": "#{@@url}/messages",
|
21
26
|
"title":"Messages"
|
@@ -70,6 +75,7 @@ class TestServer < Sinatra::Base
|
|
70
75
|
}
|
71
76
|
]
|
72
77
|
},
|
78
|
+
{ "name": "filter concepts post with spaces" },
|
73
79
|
{
|
74
80
|
"name":"filter-messages",
|
75
81
|
"method":"GET",
|
data/spec/unit/entity_spec.rb
CHANGED
@@ -231,6 +231,19 @@ describe SirenClient::Entity do
|
|
231
231
|
expect { entity.prev_page }.to raise_error Errno::ECONNREFUSED
|
232
232
|
end
|
233
233
|
end
|
234
|
+
describe '.with_raw_response' do
|
235
|
+
it 'returns the entity' do
|
236
|
+
expect(entity.with_raw_response).to eq(entity)
|
237
|
+
end
|
238
|
+
it 'sets the entity to return a raw response for the `next` request' do
|
239
|
+
entity.with_raw_response
|
240
|
+
expect(entity.next_response_is_raw?).to eq(true)
|
241
|
+
end
|
242
|
+
it 'should still allow a network request to be made' do
|
243
|
+
entity.with_raw_response
|
244
|
+
expect { entity.with_raw_response.prev_page }.to raise_error Errno::ECONNREFUSED
|
245
|
+
end
|
246
|
+
end
|
234
247
|
# Entities enumerable support
|
235
248
|
describe "enumerable support" do
|
236
249
|
describe '.each' do
|
File without changes
|
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.3.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: 2016-
|
11
|
+
date: 2016-03-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: httparty
|
@@ -190,6 +190,8 @@ files:
|
|
190
190
|
- lib/siren_client/exceptions.rb
|
191
191
|
- lib/siren_client/field.rb
|
192
192
|
- lib/siren_client/link.rb
|
193
|
+
- lib/siren_client/modules/with_raw_response.rb
|
194
|
+
- lib/siren_client/raw_response.rb
|
193
195
|
- lib/siren_client/version.rb
|
194
196
|
- siren_client.gemspec
|
195
197
|
- spec/helper/live_spec_helper.rb
|
@@ -203,6 +205,7 @@ files:
|
|
203
205
|
- spec/unit/entity_spec.rb
|
204
206
|
- spec/unit/field_spec.rb
|
205
207
|
- spec/unit/link_spec.rb
|
208
|
+
- spec/unit/raw_response.rb
|
206
209
|
homepage: https://github.com/cha55son/siren_client
|
207
210
|
licenses:
|
208
211
|
- MIT
|
@@ -239,3 +242,4 @@ test_files:
|
|
239
242
|
- spec/unit/entity_spec.rb
|
240
243
|
- spec/unit/field_spec.rb
|
241
244
|
- spec/unit/link_spec.rb
|
245
|
+
- spec/unit/raw_response.rb
|