hyperresource 0.1.9.2 → 0.1.9.3
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/lib/hyper_resource.rb +82 -82
- data/lib/hyper_resource/adapter/hal_json.rb +2 -2
- data/lib/hyper_resource/modules/http.rb +53 -50
- data/lib/hyper_resource/version.rb +2 -2
- metadata +16 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a9eb3362f2f929049439543e8aa9cd140f808b9b
|
4
|
+
data.tar.gz: 6ae500a90b57bb69715db82268d8c8e56d5af4cd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b0b44a45fba55b7bf5b7e4522a46fb04705a3d3d9aa877a516e1582819513b9f622428a847d153f9f920a37644404929ecd7dc3ce4772711bc7298916e1cf313
|
7
|
+
data.tar.gz: c6143d7034ea27cc735706edf8b4aead7bb5717f745f866721a2c8e340cd88cc5bbfb2d2d0ef3e24fc0f65353d620bfeda177d18940b2de2d3abfccfff0fe6ce
|
data/lib/hyper_resource.rb
CHANGED
@@ -1,23 +1,8 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require 'hyper_resource/links'
|
4
|
-
require 'hyper_resource/link'
|
5
|
-
require 'hyper_resource/objects'
|
6
|
-
require 'hyper_resource/response'
|
7
|
-
require 'hyper_resource/exceptions'
|
8
|
-
|
9
|
-
require 'hyper_resource/modules/utils'
|
10
|
-
require 'hyper_resource/modules/http'
|
11
|
-
|
12
|
-
require 'hyper_resource/adapter'
|
13
|
-
require 'hyper_resource/adapter/hal_json'
|
1
|
+
this_dir = File.dirname(File.absolute_path(__FILE__))
|
2
|
+
Dir.glob(this_dir + '/hyper_resource/**/*.rb') {|f| require f}
|
14
3
|
|
15
4
|
require 'pp'
|
16
5
|
|
17
|
-
## TODO:
|
18
|
-
## as_json, to_json (in adapter?)
|
19
|
-
## save, update, create, delete
|
20
|
-
|
21
6
|
class HyperResource
|
22
7
|
include HyperResource::Modules::Utils
|
23
8
|
include HyperResource::Modules::HTTP
|
@@ -117,37 +102,15 @@ public
|
|
117
102
|
HyperResource::Adapter::HAL_JSON
|
118
103
|
end
|
119
104
|
|
120
|
-
private
|
121
|
-
|
122
|
-
def init_from_resource(resource)
|
123
|
-
(self.class._hr_attributes - [:attributes, :links, :objects]).each do |attr|
|
124
|
-
self.send("#{attr}=".to_sym, resource.send(attr))
|
125
|
-
end
|
126
|
-
self.adapter.apply(self.response_object, self)
|
127
|
-
end
|
128
105
|
|
129
106
|
public
|
130
107
|
|
108
|
+
## Returns true if one or more of this object's attributes has been
|
109
|
+
## reassigned.
|
131
110
|
def changed?(*args)
|
132
111
|
attributes.changed?(*args)
|
133
112
|
end
|
134
113
|
|
135
|
-
## Returns a new HyperResource based on the given link href.
|
136
|
-
def _new_from_link(href)
|
137
|
-
self.class.new(:root => self.root,
|
138
|
-
:auth => self.auth,
|
139
|
-
:headers => self.headers,
|
140
|
-
:namespace => self.namespace,
|
141
|
-
:href => href)
|
142
|
-
end
|
143
|
-
|
144
|
-
def to_response_class
|
145
|
-
response_class = self.get_response_class
|
146
|
-
return self if self.class == response_class
|
147
|
-
response_class.new(self)
|
148
|
-
end
|
149
|
-
|
150
|
-
|
151
114
|
## +incoming_body_filter+ filters a hash of attribute keys and values
|
152
115
|
## on their way from a response body to a HyperResource. Override this
|
153
116
|
## in a subclass of HyperResource to implement filters on incoming data.
|
@@ -171,30 +134,83 @@ public
|
|
171
134
|
end
|
172
135
|
|
173
136
|
|
174
|
-
|
175
|
-
|
176
|
-
|
137
|
+
## Returns the first object in the first collection of objects embedded
|
138
|
+
## in this resource. Equivalent to +self.objects.first+.
|
139
|
+
def first; self.objects.first end
|
140
|
+
|
141
|
+
## Returns the *i*th object in the first collection of objects embedded
|
142
|
+
## in this resource. Equivalent to +self.objects[i]+.
|
143
|
+
def [](i); self.objects.ith(i) end
|
144
|
+
|
145
|
+
## method_missing will load this resource if not yet loaded, then
|
146
|
+
## attempt to delegate to +attributes+, then +objects+, then +links+.
|
147
|
+
## Override with care.
|
148
|
+
def method_missing(method, *args)
|
149
|
+
self.get unless self.loaded
|
150
|
+
|
151
|
+
method = method.to_s
|
152
|
+
if method[-1] == '='
|
153
|
+
return attributes[method[0..-2]] = args.first if attributes[method[0..-2]]
|
154
|
+
else
|
155
|
+
return attributes[method] if attributes && attributes[method]
|
156
|
+
return objects[method] if objects && objects[method]
|
157
|
+
if links && links[method]
|
158
|
+
if args.count > 0
|
159
|
+
return links[method].where(*args)
|
160
|
+
else
|
161
|
+
return links[method]
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
raise NoMethodError, "undefined method `#{method}' for #{self.inspect}"
|
167
|
+
end
|
168
|
+
|
169
|
+
|
170
|
+
def inspect # :nodoc:
|
171
|
+
"#<#{self.class}:0x#{"%x" % self.object_id} @root=#{self.root.inspect} "+
|
172
|
+
"@href=#{self.href.inspect} @loaded=#{self.loaded} "+
|
173
|
+
"@namespace=#{self.namespace.inspect} ...>"
|
177
174
|
end
|
178
175
|
|
176
|
+
## +response_body+ is deprecated in favor of +response_object+.
|
177
|
+
def response_body; response_object end # :nodoc:
|
178
|
+
|
179
|
+
|
180
|
+
#######################################################################
|
181
|
+
#### Underscored functions are not meant to be used outside of ####
|
182
|
+
#### HyperResource machinery. You have been warned. ####
|
183
|
+
|
184
|
+
|
185
|
+
## Return a new HyperResource based on this object and a given href.
|
186
|
+
def _new_from_link(href) # :nodoc:
|
187
|
+
self.class.new(:root => self.root,
|
188
|
+
:auth => self.auth,
|
189
|
+
:headers => self.headers,
|
190
|
+
:namespace => self.namespace,
|
191
|
+
:href => href)
|
192
|
+
end
|
193
|
+
|
194
|
+
|
179
195
|
## Returns the class into which the given response should be cast.
|
180
196
|
## If the object is not loaded yet, or if +opts[:namespace]+ is
|
181
197
|
## not set, returns +self+.
|
182
198
|
##
|
183
|
-
## Otherwise, +
|
199
|
+
## Otherwise, +_get_response_class+ uses +_get_response_data_type+ to
|
184
200
|
## determine subclass name, glues it to the given namespace, and
|
185
201
|
## creates the class if it's not there yet. E.g., given a namespace of
|
186
202
|
## +FooAPI+ and a response content-type of
|
187
203
|
## "application/vnd.foocorp.fooapi.v1+json;type=User", this should
|
188
204
|
## return +FooAPI::User+ (even if +FooAPI::User+ hadn't existed yet).
|
189
205
|
|
190
|
-
def self.
|
206
|
+
def self._get_response_class(response, namespace) # :nodoc:
|
191
207
|
if self.to_s == 'HyperResource'
|
192
208
|
return self unless namespace
|
193
209
|
end
|
194
210
|
|
195
211
|
namespace ||= self.to_s
|
196
212
|
|
197
|
-
type_name = self.
|
213
|
+
type_name = self._get_response_data_type(response)
|
198
214
|
return self unless type_name
|
199
215
|
|
200
216
|
class_name = "#{namespace}::#{type_name}"
|
@@ -216,11 +232,12 @@ public
|
|
216
232
|
eval(class_name)
|
217
233
|
end
|
218
234
|
|
219
|
-
|
220
|
-
|
221
|
-
self.class.
|
235
|
+
def _get_response_class # :nodoc:
|
236
|
+
self.namespace ||= self.class.to_s unless self.class.to_s=='HyperResource'
|
237
|
+
self.class._get_response_class(self.response, self.namespace)
|
222
238
|
end
|
223
239
|
|
240
|
+
|
224
241
|
## Inspects the given response, and returns a string describing this
|
225
242
|
## resource's data type.
|
226
243
|
##
|
@@ -229,48 +246,31 @@ public
|
|
229
246
|
##
|
230
247
|
## Override this method in a subclass to alter HyperResource's behavior.
|
231
248
|
|
232
|
-
def self.
|
249
|
+
def self._get_response_data_type(response) # :nodoc:
|
233
250
|
return nil unless response
|
234
251
|
return nil unless content_type = response['content-type']
|
235
252
|
return nil unless m=content_type.match(/;\s* type=(?<type> [0-9A-Za-z:]+)/x)
|
236
253
|
m[:type][0].upcase + m[:type][1..-1]
|
237
254
|
end
|
238
255
|
|
239
|
-
|
240
|
-
|
241
|
-
## Returns the first object in the first collection of objects embedded
|
242
|
-
## in this resource. Equivalent to +self.objects.first+.
|
243
|
-
def first; self.objects.first end
|
244
|
-
|
245
|
-
## Returns the *i*th object in the first collection of objects embedded
|
246
|
-
## in this resource. Equivalent to +self.objects[i]+.
|
247
|
-
def [](i); self.objects.ith(i) end
|
248
|
-
|
249
|
-
## method_missing will load this resource if not yet loaded, then
|
250
|
-
## attempt to delegate to +attributes+, then +objects+, then +links+.
|
251
|
-
def method_missing(method, *args)
|
252
|
-
self.get unless self.loaded
|
253
|
-
|
254
|
-
method = method.to_s
|
255
|
-
if method[-1] == '='
|
256
|
-
return attributes[method[0..-2]] = args.first if attributes[method[0..-2]]
|
257
|
-
else
|
258
|
-
return attributes[method] if attributes && attributes[method]
|
259
|
-
return objects[method] if objects && objects[method]
|
260
|
-
return links[method] if links && links[method]
|
261
|
-
end
|
262
|
-
|
263
|
-
raise NoMethodError, "undefined method `#{method}' for #{self.inspect}"
|
256
|
+
def _get_response_data_type # :nodoc:
|
257
|
+
self.class._get_response_data_type(self.response)
|
264
258
|
end
|
265
259
|
|
260
|
+
private
|
266
261
|
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
262
|
+
## Return this object, "cast" into its proper response class.
|
263
|
+
def to_response_class # :nodoc:
|
264
|
+
response_class = self._get_response_class
|
265
|
+
return self if self.class == response_class
|
266
|
+
response_class.new(self)
|
271
267
|
end
|
272
268
|
|
273
|
-
|
274
|
-
|
269
|
+
def init_from_resource(resource)
|
270
|
+
(self.class._hr_attributes - [:attributes, :links, :objects]).each do |attr|
|
271
|
+
self.send("#{attr}=".to_sym, resource.send(attr))
|
272
|
+
end
|
273
|
+
self.adapter.apply(self.response_object, self)
|
274
|
+
end
|
275
275
|
|
276
276
|
end
|
@@ -58,7 +58,7 @@ class HyperResource
|
|
58
58
|
|
59
59
|
def apply_links(resp, rsrc)
|
60
60
|
return unless resp['_links']
|
61
|
-
rsrc.links = rsrc.
|
61
|
+
rsrc.links = rsrc._get_response_class::Links.new(rsrc)
|
62
62
|
links = rsrc.links
|
63
63
|
|
64
64
|
resp['_links'].each do |rel, link_spec|
|
@@ -80,7 +80,7 @@ class HyperResource
|
|
80
80
|
|
81
81
|
|
82
82
|
def apply_attributes(resp, rsrc)
|
83
|
-
rsrc.attributes = rsrc.
|
83
|
+
rsrc.attributes = rsrc._get_response_class::Attributes.new(rsrc)
|
84
84
|
|
85
85
|
given_attrs = resp.reject{|k,v| %w(_links _embedded).include?(k)}
|
86
86
|
filtered_attrs = rsrc.incoming_body_filter(given_attrs)
|
@@ -2,62 +2,65 @@ require 'faraday'
|
|
2
2
|
require 'uri'
|
3
3
|
require 'json'
|
4
4
|
|
5
|
-
module HyperResource::Modules
|
6
|
-
|
7
|
-
## Loads and returns the resource pointed to by +href+. The returned
|
8
|
-
## resource will be blessed into its "proper" class, if
|
9
|
-
## +self.class.namespace != nil+.
|
10
|
-
def get
|
11
|
-
self.response = faraday_connection.get(self.href || '')
|
12
|
-
finish_up
|
13
|
-
end
|
5
|
+
module HyperResource::Modules
|
6
|
+
module HTTP
|
14
7
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
fc = Faraday.new(:url => url)
|
22
|
-
fc.headers.merge!('User-Agent' => "HyperResource #{HyperResource::VERSION}")
|
23
|
-
fc.headers.merge!(self.headers || {})
|
24
|
-
if ba=self.auth[:basic]
|
25
|
-
fc.basic_auth(*ba)
|
8
|
+
## Loads and returns the resource pointed to by +href+. The returned
|
9
|
+
## resource will be blessed into its "proper" class, if
|
10
|
+
## +self.class.namespace != nil+.
|
11
|
+
def get
|
12
|
+
self.response = faraday_connection.get(self.href || '')
|
13
|
+
finish_up
|
26
14
|
end
|
27
|
-
Thread.current[key] = fc
|
28
|
-
end
|
29
15
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
16
|
+
## Returns a per-thread Faraday connection for this object.
|
17
|
+
def faraday_connection(url=nil)
|
18
|
+
url ||= self.root
|
19
|
+
key = "faraday_connection_#{url}"
|
20
|
+
return Thread.current[key] if Thread.current[key]
|
21
|
+
|
22
|
+
fc = Faraday.new(:url => url)
|
23
|
+
fc.headers.merge!('User-Agent' => "HyperResource #{HyperResource::VERSION}")
|
24
|
+
fc.headers.merge!(self.headers || {})
|
25
|
+
if ba=self.auth[:basic]
|
26
|
+
fc.basic_auth(*ba)
|
27
|
+
end
|
28
|
+
Thread.current[key] = fc
|
41
29
|
end
|
42
30
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
31
|
+
private
|
32
|
+
|
33
|
+
def finish_up
|
34
|
+
begin
|
35
|
+
self.response_object = self.adapter.deserialize(self.response.body)
|
36
|
+
rescue Exception => e
|
37
|
+
raise HyperResource::ResponseError.new(
|
38
|
+
"Error when deserializing response body",
|
39
|
+
:response => self.response,
|
40
|
+
:cause => e
|
41
|
+
)
|
42
|
+
end
|
43
|
+
|
44
|
+
self.adapter.apply(self.response_object, self)
|
45
|
+
self.loaded = true
|
46
|
+
|
47
|
+
status = self.response.status
|
48
|
+
if status / 100 == 2
|
49
|
+
return to_response_class
|
50
|
+
elsif status / 100 == 3
|
51
|
+
## TODO redirect logic?
|
52
|
+
elsif status / 100 == 4
|
53
|
+
raise HyperResource::ClientError.new(status.to_s,
|
54
|
+
:response => self.response)
|
55
|
+
elsif status / 100 == 5
|
56
|
+
raise HyperResource::ServerError.new(status.to_s,
|
59
57
|
:response => self.response)
|
58
|
+
else ## 1xx? really?
|
59
|
+
raise HyperResource::ResponseError.new("Got status #{status}, wtf?",
|
60
|
+
:response => self.response)
|
61
|
+
end
|
60
62
|
end
|
61
|
-
end
|
62
63
|
|
64
|
+
end
|
63
65
|
end
|
66
|
+
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hyperresource
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.9.
|
4
|
+
version: 0.1.9.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Pete Gamache
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-
|
11
|
+
date: 2013-10-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: uri_template
|
@@ -80,6 +80,20 @@ dependencies:
|
|
80
80
|
- - '>='
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: 0.13.3
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: sinatra
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 1.4.0
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 1.4.0
|
83
97
|
description: |2
|
84
98
|
HyperResource is a hypermedia client library for Ruby. Its goals are to
|
85
99
|
interface directly with well-behaved hypermedia APIs, to allow the data
|