hal-client 1.3.1 → 1.4.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 +17 -5
- data/lib/hal_client/representation.rb +65 -23
- data/lib/hal_client/version.rb +1 -1
- data/spec/hal_client/representation_spec.rb +25 -2
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b2ff485e8014f90b3dff0a1dfce149d179dd9cd1
|
4
|
+
data.tar.gz: 52d3c6654272fbca9b80e69c4506182c524a1f46
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5ab224fd14a959818ce357dc71926fee813f90cc1f583d94c547e0842fabffad307021f285924d9193056b29e3a2b2670f89e55b56626688fbe488a9fc2edbd5
|
7
|
+
data.tar.gz: 31932812f8c8472d4dfd55515e8781c3407627709daf6ce6a25a01c0d5a1064069986bc428c64bfeb85e54addc73911215e15d7035976f7b1da384c0be710f36
|
data/README.md
CHANGED
@@ -39,14 +39,16 @@ Once we have a representation we will want to navigate its links. This can be ac
|
|
39
39
|
articles = blog.related("item")
|
40
40
|
# => #<RepresentationSet:...>
|
41
41
|
|
42
|
-
In the example above `item` is the link rel. The `#related` method extracts embedded representations and
|
42
|
+
In the example above `item` is the link rel. The `#related` method extracts embedded representations and link hrefs with the specified rel. The resulting representations are packaged into a `HalClient::RepresentationSet`. `HalClient` always returns `RepresentationSet`s when following links, even when there is only one result. `RepresentationSet`s are `Enumerable` so they expose all your favorite methods like `#each`, `#map`, `#any?`, etc. `RepresentationSet`s expose a `#related` method which calls `#related` on each member of the set and then merges the results into a new representation set.
|
43
43
|
|
44
|
-
|
45
|
-
|
46
|
-
authors = blog.related("author").related("item")
|
47
|
-
authors.first.property("name")
|
44
|
+
all_the_authors = blog.related("author").related("item")
|
45
|
+
all_the_authors.first.property("name")
|
48
46
|
# => "Bob Smith"
|
49
47
|
|
48
|
+
#### Request timing
|
49
|
+
|
50
|
+
If the `author` relationship was a link in the above example the HTTP GET to retrieve Bob's representation from the server does not happen until the `#property` method is called. This lazy dereferencing allows for working with efficiently with larger relationship sets.
|
51
|
+
|
50
52
|
#### CURIEs
|
51
53
|
|
52
54
|
Links specified using a compact URI (or CURIE) as the rel are fully supported. They are accessed using the fully expanded version of the curie. For example, given a representations of an author:
|
@@ -94,6 +96,16 @@ If the API uses one or more a custom mime types we can specify that they be incl
|
|
94
96
|
my_client.get("http://blog.me/")
|
95
97
|
# => #<Representation: http://blog.me/>
|
96
98
|
|
99
|
+
### Parsing presentations from clients
|
100
|
+
|
101
|
+
HalClient can be used by servers of HAL APIs to interpret the bodies of requests. For example,
|
102
|
+
|
103
|
+
new_post_repr = HalClient::Representation.new(JSON.load(request.raw_post))
|
104
|
+
author = Author.by_href(new_post_repr.related('author').first.href)
|
105
|
+
new_post = Post.new title: new_post_repr['title'], author: author, #...
|
106
|
+
|
107
|
+
Created this way the representation will not dereference any links (because it doesn't have a HalClient) but it will provide `HalClient::Representation`s of both embedded and linked resources.
|
108
|
+
|
97
109
|
## Contributing
|
98
110
|
|
99
111
|
1. Fork it ( http://github.com/pezra/hal-client/fork )
|
@@ -13,12 +13,48 @@ class HalClient
|
|
13
13
|
|
14
14
|
# Create a new Representation
|
15
15
|
#
|
16
|
-
# hal_client - The HalClient instance to use when navigating.
|
17
16
|
# parsed_json - A hash structure representing a single HAL
|
18
17
|
# document.
|
19
|
-
|
20
|
-
|
21
|
-
|
18
|
+
# href - The href of this representation.
|
19
|
+
# hal_client - The HalClient instance to use when navigating.
|
20
|
+
#
|
21
|
+
# Signature
|
22
|
+
#
|
23
|
+
# initialize(hal_client, parsed_json)
|
24
|
+
# initialize(parsed_json, hal_client)
|
25
|
+
#
|
26
|
+
# Initialize this representation with a parsed json document and a
|
27
|
+
# hal_client with which to make requests.
|
28
|
+
#
|
29
|
+
# initialize(href, hal_client)
|
30
|
+
#
|
31
|
+
# Initialize this representation with an href and a hal_client
|
32
|
+
# with which to make requests. Any attempt to retrieve properties
|
33
|
+
# or related representations will result in the href being
|
34
|
+
# dereferenced.
|
35
|
+
#
|
36
|
+
# initialize(href)
|
37
|
+
#
|
38
|
+
# Initialize this representation with an href. The representation
|
39
|
+
# will not be able to make requests to dereference itself but this
|
40
|
+
# can still be useful in test situations to maintain a uniform
|
41
|
+
# interface.
|
42
|
+
#
|
43
|
+
# initialize(parse_json)
|
44
|
+
#
|
45
|
+
# Initializes representation that cannot request related
|
46
|
+
# representations.
|
47
|
+
#
|
48
|
+
def initialize(*args)
|
49
|
+
(raise ArgumentError, "wrong number of arguments (#{args.size} for 1 or 2)") if
|
50
|
+
args.size > 2
|
51
|
+
|
52
|
+
@raw = args.find {|it| (it.respond_to? :has_key?) && (it.respond_to? :fetch) }
|
53
|
+
@hal_client = args.find {|it| HalClient === it }
|
54
|
+
|
55
|
+
if @raw.nil?
|
56
|
+
@href = args.find {|it| it.respond_to? :downcase }
|
57
|
+
end
|
22
58
|
end
|
23
59
|
|
24
60
|
# Returns The value of the specified property or the specified
|
@@ -41,7 +77,7 @@ class HalClient
|
|
41
77
|
|
42
78
|
# Returns the URL of the resource this representation represents.
|
43
79
|
def href
|
44
|
-
link_section.fetch("self").fetch("href")
|
80
|
+
@href ||= link_section.fetch("self").fetch("href")
|
45
81
|
end
|
46
82
|
|
47
83
|
# Returns the value of the specified property or representations
|
@@ -92,8 +128,8 @@ class HalClient
|
|
92
128
|
raise KeyError, "No resources are related via `#{link_rel}`"
|
93
129
|
}
|
94
130
|
|
95
|
-
embedded =
|
96
|
-
linked =
|
131
|
+
embedded = embedded_or_nil(link_rel)
|
132
|
+
linked = linked_or_nil(link_rel, options)
|
97
133
|
|
98
134
|
if !embedded.nil? or !linked.nil?
|
99
135
|
RepresentationSet.new (Array(embedded) + Array(linked))
|
@@ -115,20 +151,8 @@ class HalClient
|
|
115
151
|
# Raises KeyError if the specified link does not exist
|
116
152
|
# and no default_proc is provided.
|
117
153
|
def related_hrefs(link_rel, options={}, &default_proc)
|
118
|
-
|
119
|
-
|
120
|
-
}
|
121
|
-
|
122
|
-
embedded = boxed embedded_section.fetch(link_rel, nil)
|
123
|
-
linked = boxed link_section.fetch(link_rel, nil)
|
124
|
-
|
125
|
-
if !embedded.nil? or !linked.nil?
|
126
|
-
Array(embedded).map{|it| it.fetch("_links").fetch("self").fetch("href") rescue nil} +
|
127
|
-
Array(linked).map{|it| it.fetch("href", nil) }.
|
128
|
-
compact
|
129
|
-
else
|
130
|
-
default_proc.call link_rel
|
131
|
-
end
|
154
|
+
related(link_rel, options, &default_proc).
|
155
|
+
map(&:href)
|
132
156
|
end
|
133
157
|
|
134
158
|
# Returns a short human readable description of this
|
@@ -138,10 +162,14 @@ class HalClient
|
|
138
162
|
end
|
139
163
|
|
140
164
|
protected
|
141
|
-
attr_reader :
|
165
|
+
attr_reader :hal_client
|
142
166
|
|
143
167
|
MISSING = Object.new
|
144
168
|
|
169
|
+
def raw
|
170
|
+
@raw ||= hal_client.get(href)
|
171
|
+
end
|
172
|
+
|
145
173
|
def link_section
|
146
174
|
@link_section ||= fully_qualified raw.fetch("_links", {})
|
147
175
|
end
|
@@ -156,12 +184,26 @@ class HalClient
|
|
156
184
|
relations.map{|it| Representation.new hal_client, it}
|
157
185
|
end
|
158
186
|
|
187
|
+
def embedded_or_nil(link_rel)
|
188
|
+
embedded link_rel
|
189
|
+
|
190
|
+
rescue KeyError
|
191
|
+
nil
|
192
|
+
end
|
193
|
+
|
159
194
|
def linked(link_rel, options)
|
160
195
|
relations = boxed link_section.fetch(link_rel)
|
161
196
|
|
162
197
|
relations.
|
163
198
|
map {|link| href_from link, options }.
|
164
|
-
map {|href|
|
199
|
+
map {|href| Representation.new href, hal_client }
|
200
|
+
end
|
201
|
+
|
202
|
+
def linked_or_nil(link_rel, options)
|
203
|
+
linked link_rel, options
|
204
|
+
|
205
|
+
rescue KeyError
|
206
|
+
nil
|
165
207
|
end
|
166
208
|
|
167
209
|
|
data/lib/hal_client/version.rb
CHANGED
@@ -3,12 +3,11 @@ require_relative "../spec_helper"
|
|
3
3
|
require "hal_client/representation"
|
4
4
|
|
5
5
|
describe HalClient::Representation do
|
6
|
-
describe ".new" do
|
6
|
+
describe ".new(a_hal_client, a_parsed_json_doc)" do
|
7
7
|
let!(:return_val) { described_class.new(a_client, MultiJson.load(raw_repr)) }
|
8
8
|
describe "return_val" do
|
9
9
|
subject { return_val }
|
10
10
|
it { should be_kind_of described_class }
|
11
|
-
|
12
11
|
end
|
13
12
|
end
|
14
13
|
|
@@ -231,3 +230,27 @@ HAL
|
|
231
230
|
}
|
232
231
|
end
|
233
232
|
end
|
233
|
+
|
234
|
+
describe HalClient::Representation, "w/o hal_client" do
|
235
|
+
subject(:repr) { described_class.new(MultiJson.load(raw_repr)) }
|
236
|
+
|
237
|
+
specify { expect(subject.href).to eq "http://example.com/foo" }
|
238
|
+
specify { expect(subject.related_hrefs "link1").to include "http://example.com/bar" }
|
239
|
+
specify { expect(subject.related("link1").first.href).to eq "http://example.com/bar" }
|
240
|
+
specify { expect(subject.related("embed1").first.href).to eq "http://example.com/baz" }
|
241
|
+
|
242
|
+
|
243
|
+
let(:raw_repr) { <<-HAL }
|
244
|
+
{ "prop1": 1
|
245
|
+
,"_links": {
|
246
|
+
"self": { "href": "http://example.com/foo" }
|
247
|
+
,"link1": { "href": "http://example.com/bar" }
|
248
|
+
}
|
249
|
+
,"_embedded": {
|
250
|
+
"embed1": {
|
251
|
+
"_links": { "self": { "href": "http://example.com/baz" }}
|
252
|
+
}
|
253
|
+
}
|
254
|
+
}
|
255
|
+
HAL
|
256
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hal-client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Peter Williams
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-03-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rest-client
|