activeresource 5.1.1 → 6.0.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 +324 -0
- data/lib/active_resource/associations/builder/association.rb +1 -2
- data/lib/active_resource/associations.rb +2 -2
- data/lib/active_resource/base.rb +73 -36
- data/lib/active_resource/collection.rb +2 -2
- data/lib/active_resource/connection.rb +8 -5
- data/lib/active_resource/exceptions.rb +13 -3
- data/lib/active_resource/http_mock.rb +5 -7
- data/lib/active_resource/inheriting_hash.rb +15 -0
- data/lib/active_resource/railtie.rb +1 -1
- data/lib/active_resource/reflection.rb +2 -2
- data/lib/active_resource/schema.rb +1 -0
- data/lib/active_resource/singleton.rb +0 -2
- data/lib/active_resource/threadsafe_attributes.rb +0 -1
- data/lib/active_resource/validations.rb +5 -5
- data/lib/active_resource/version.rb +4 -4
- data/lib/active_resource.rb +1 -0
- metadata +32 -28
- data/README.rdoc +0 -285
- data/lib/active_resource/observing.rb +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f2a0c925e2619c4a4204eebdaea70776a57fec944e9eefeb98982ed8cf425bbc
|
4
|
+
data.tar.gz: b77c66a74c3fe0d32e16d0ce4eaaec1c772200bda9ea36b2bfba1a3cc4f58b5d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9116078833a262f5a4d184a9cd080f3a29bfc5c07481cf352dd87baa735ba0dfae6159a35ac37ea1ad2e121348a33d958151a048af8dbb6e85e3a387076de3b5
|
7
|
+
data.tar.gz: 02e8b7e3aa1fd89f70f67b2696d778bf0c4a5d89c4b6f779ec3ecffc6a099374c06515ec2bfcb4e7175a518f00543f16b1b691670378c2533fcf353ce82cb96f
|
data/README.md
ADDED
@@ -0,0 +1,324 @@
|
|
1
|
+
# Active Resource
|
2
|
+
|
3
|
+
Active Resource (ARes) connects business objects and Representational State Transfer (REST)
|
4
|
+
web services. It implements object-relational mapping for REST web services to provide transparent
|
5
|
+
proxying capabilities between a client (Active Resource) and a RESTful service (which is provided by
|
6
|
+
Simply RESTful routing in `ActionController::Resources`).
|
7
|
+
|
8
|
+
## Philosophy
|
9
|
+
|
10
|
+
Active Resource attempts to provide a coherent wrapper object-relational mapping for REST
|
11
|
+
web services. It follows the same philosophy as Active Record, in that one of its prime aims
|
12
|
+
is to reduce the amount of code needed to map to these resources. This is made possible
|
13
|
+
by relying on a number of code- and protocol-based conventions that make it easy for Active Resource
|
14
|
+
to infer complex relations and structures. These conventions are outlined in detail in the documentation
|
15
|
+
for `ActiveResource::Base`.
|
16
|
+
|
17
|
+
## Overview
|
18
|
+
|
19
|
+
Model classes are mapped to remote REST resources by Active Resource much the same way Active Record maps
|
20
|
+
model classes to database tables. When a request is made to a remote resource, a REST JSON request is
|
21
|
+
generated, transmitted, and the result received and serialized into a usable Ruby object.
|
22
|
+
|
23
|
+
## Download and installation
|
24
|
+
|
25
|
+
The latest version of Active Resource can be installed with RubyGems:
|
26
|
+
|
27
|
+
```
|
28
|
+
gem install activeresource
|
29
|
+
```
|
30
|
+
|
31
|
+
Or added to a Gemfile:
|
32
|
+
|
33
|
+
```ruby
|
34
|
+
gem 'activeresource'
|
35
|
+
```
|
36
|
+
|
37
|
+
Source code can be downloaded on GitHub
|
38
|
+
|
39
|
+
* https://github.com/rails/activeresource/tree/main
|
40
|
+
|
41
|
+
### Configuration and Usage
|
42
|
+
|
43
|
+
Putting Active Resource to use is very similar to Active Record. It's as simple as creating a model class
|
44
|
+
that inherits from `ActiveResource::Base` and providing a `site` class variable to it:
|
45
|
+
|
46
|
+
```ruby
|
47
|
+
class Person < ActiveResource::Base
|
48
|
+
self.site = "http://api.people.com:3000"
|
49
|
+
end
|
50
|
+
```
|
51
|
+
|
52
|
+
Now the Person class is REST enabled and can invoke REST services very similarly to how Active Record invokes
|
53
|
+
life cycle methods that operate against a persistent store.
|
54
|
+
|
55
|
+
```ruby
|
56
|
+
# Find a person with id = 1
|
57
|
+
tyler = Person.find(1)
|
58
|
+
Person.exists?(1) # => true
|
59
|
+
```
|
60
|
+
|
61
|
+
As you can see, the methods are quite similar to Active Record's methods for dealing with database
|
62
|
+
records. But rather than dealing directly with a database record, you're dealing with HTTP resources
|
63
|
+
(which may or may not be database records).
|
64
|
+
|
65
|
+
Connection settings (`site`, `headers`, `user`, `password`, `bearer_token`, `proxy`) and the connections
|
66
|
+
themselves are store in thread-local variables to make them thread-safe, so you can also set these
|
67
|
+
dynamically, even in a multi-threaded environment, for instance:
|
68
|
+
|
69
|
+
```ruby
|
70
|
+
ActiveResource::Base.site = api_site_for(request)
|
71
|
+
```
|
72
|
+
### Authentication
|
73
|
+
|
74
|
+
Active Resource supports the token based authentication provided by Rails through the
|
75
|
+
`ActionController::HttpAuthentication::Token` class using custom headers.
|
76
|
+
|
77
|
+
```ruby
|
78
|
+
class Person < ActiveResource::Base
|
79
|
+
self.headers['Authorization'] = 'Token token="abcd"'
|
80
|
+
end
|
81
|
+
```
|
82
|
+
|
83
|
+
You can also set any specific HTTP header using the same way. As mentioned above, headers are
|
84
|
+
thread-safe, so you can set headers dynamically, even in a multi-threaded environment:
|
85
|
+
|
86
|
+
```ruby
|
87
|
+
ActiveResource::Base.headers['Authorization'] = current_session_api_token
|
88
|
+
```
|
89
|
+
|
90
|
+
Active Resource supports 2 options for HTTP authentication today.
|
91
|
+
|
92
|
+
1. Basic
|
93
|
+
```ruby
|
94
|
+
class Person < ActiveResource::Base
|
95
|
+
self.user = 'my@email.com'
|
96
|
+
self.password = '123'
|
97
|
+
end
|
98
|
+
# username: my@email.com password: 123
|
99
|
+
```
|
100
|
+
|
101
|
+
2. Bearer Token
|
102
|
+
```ruby
|
103
|
+
class Person < ActiveResource::Base
|
104
|
+
self.auth_type = :bearer
|
105
|
+
self.bearer_token = 'my-token123'
|
106
|
+
end
|
107
|
+
# Bearer my-token123
|
108
|
+
```
|
109
|
+
|
110
|
+
### Protocol
|
111
|
+
|
112
|
+
Active Resource is built on a standard JSON or XML format for requesting and submitting resources
|
113
|
+
over HTTP. It mirrors the RESTful routing built into Action Controller but will also work with any
|
114
|
+
other REST service that properly implements the protocol. REST uses HTTP, but unlike "typical" web
|
115
|
+
applications, it makes use of all the verubys available in the HTTP specification:
|
116
|
+
|
117
|
+
* GET requests are used for finding and retrieving resources.
|
118
|
+
* POST requests are used to create new resources.
|
119
|
+
* PUT requests are used to update existing resources.
|
120
|
+
* DELETE requests are used to delete resources.
|
121
|
+
|
122
|
+
For more information on how this protocol works with Active Resource, see the `ActiveResource::Base` documentation;
|
123
|
+
for more general information on REST web services, see the article
|
124
|
+
[here](http://en.wikipedia.org/wiki/Representational_State_Transfer).
|
125
|
+
|
126
|
+
### Find
|
127
|
+
|
128
|
+
Find requests use the GET method and expect the JSON form of whatever resource/resources is/are
|
129
|
+
being requested. So, for a request for a single element, the JSON of that item is expected in
|
130
|
+
response:
|
131
|
+
|
132
|
+
```ruby
|
133
|
+
# Expects a response of
|
134
|
+
#
|
135
|
+
# {"id":1,"first":"Tyler","last":"Durden"}
|
136
|
+
#
|
137
|
+
# for GET http://api.people.com:3000/people/1.json
|
138
|
+
#
|
139
|
+
tyler = Person.find(1)
|
140
|
+
```
|
141
|
+
|
142
|
+
The JSON document that is received is used to build a new object of type Person, with each
|
143
|
+
JSON element becoming an attribute on the object.
|
144
|
+
|
145
|
+
```ruby
|
146
|
+
tyler.is_a? Person # => true
|
147
|
+
tyler.last # => 'Durden'
|
148
|
+
```
|
149
|
+
|
150
|
+
Any complex element (one that contains other elements) becomes its own object:
|
151
|
+
|
152
|
+
```ruby
|
153
|
+
# With this response:
|
154
|
+
# {"id":1,"first":"Tyler","address":{"street":"Paper St.","state":"CA"}}
|
155
|
+
#
|
156
|
+
# for GET http://api.people.com:3000/people/1.json
|
157
|
+
#
|
158
|
+
tyler = Person.find(1)
|
159
|
+
tyler.address # => <Person::Address::xxxxx>
|
160
|
+
tyler.address.street # => 'Paper St.'
|
161
|
+
```
|
162
|
+
|
163
|
+
Collections can also be requested in a similar fashion
|
164
|
+
|
165
|
+
```ruby
|
166
|
+
# Expects a response of
|
167
|
+
#
|
168
|
+
# [
|
169
|
+
# {"id":1,"first":"Tyler","last":"Durden"},
|
170
|
+
# {"id":2,"first":"Tony","last":"Stark",}
|
171
|
+
# ]
|
172
|
+
#
|
173
|
+
# for GET http://api.people.com:3000/people.json
|
174
|
+
#
|
175
|
+
people = Person.all
|
176
|
+
people.first # => <Person::xxx 'first' => 'Tyler' ...>
|
177
|
+
people.last # => <Person::xxx 'first' => 'Tony' ...>
|
178
|
+
```
|
179
|
+
|
180
|
+
### Create
|
181
|
+
|
182
|
+
Creating a new resource submits the JSON form of the resource as the body of the request and expects
|
183
|
+
a 'Location' header in the response with the RESTful URL location of the newly created resource. The
|
184
|
+
id of the newly created resource is parsed out of the Location response header and automatically set
|
185
|
+
as the id of the ARes object.
|
186
|
+
|
187
|
+
```ruby
|
188
|
+
# {"first":"Tyler","last":"Durden"}
|
189
|
+
#
|
190
|
+
# is submitted as the body on
|
191
|
+
#
|
192
|
+
# if include_root_in_json is not set or set to false => {"first":"Tyler"}
|
193
|
+
# if include_root_in_json is set to true => {"person":{"first":"Tyler"}}
|
194
|
+
#
|
195
|
+
# POST http://api.people.com:3000/people.json
|
196
|
+
#
|
197
|
+
# when save is called on a new Person object. An empty response is
|
198
|
+
# is expected with a 'Location' header value:
|
199
|
+
#
|
200
|
+
# Response (201): Location: http://api.people.com:3000/people/2
|
201
|
+
#
|
202
|
+
tyler = Person.new(:first => 'Tyler')
|
203
|
+
tyler.new? # => true
|
204
|
+
tyler.save # => true
|
205
|
+
tyler.new? # => false
|
206
|
+
tyler.id # => 2
|
207
|
+
```
|
208
|
+
|
209
|
+
### Update
|
210
|
+
|
211
|
+
'save' is also used to update an existing resource and follows the same protocol as creating a resource
|
212
|
+
with the exception that no response headers are needed -- just an empty response when the update on the
|
213
|
+
server side was successful.
|
214
|
+
|
215
|
+
```ruby
|
216
|
+
# {"first":"Tyler"}
|
217
|
+
#
|
218
|
+
# is submitted as the body on
|
219
|
+
#
|
220
|
+
# if include_root_in_json is not set or set to false => {"first":"Tyler"}
|
221
|
+
# if include_root_in_json is set to true => {"person":{"first":"Tyler"}}
|
222
|
+
#
|
223
|
+
# PUT http://api.people.com:3000/people/1.json
|
224
|
+
#
|
225
|
+
# when save is called on an existing Person object. An empty response is
|
226
|
+
# is expected with code (204)
|
227
|
+
#
|
228
|
+
tyler = Person.find(1)
|
229
|
+
tyler.first # => 'Tyler'
|
230
|
+
tyler.first = 'Tyson'
|
231
|
+
tyler.save # => true
|
232
|
+
```
|
233
|
+
|
234
|
+
### Delete
|
235
|
+
|
236
|
+
Destruction of a resource can be invoked as a class and instance method of the resource.
|
237
|
+
|
238
|
+
```ruby
|
239
|
+
# A request is made to
|
240
|
+
#
|
241
|
+
# DELETE http://api.people.com:3000/people/1.json
|
242
|
+
#
|
243
|
+
# for both of these forms. An empty response with
|
244
|
+
# is expected with response code (200)
|
245
|
+
#
|
246
|
+
tyler = Person.find(1)
|
247
|
+
tyler.destroy # => true
|
248
|
+
tyler.exists? # => false
|
249
|
+
Person.delete(2) # => true
|
250
|
+
Person.exists?(2) # => false
|
251
|
+
```
|
252
|
+
|
253
|
+
### Associations
|
254
|
+
|
255
|
+
Relationships between resources can be declared using the standard association syntax
|
256
|
+
that should be familiar to anyone who uses Active Record. For example, using the
|
257
|
+
class definition below:
|
258
|
+
|
259
|
+
```ruby
|
260
|
+
class Post < ActiveResource::Base
|
261
|
+
self.site = "http://blog.io"
|
262
|
+
has_many :comments
|
263
|
+
end
|
264
|
+
|
265
|
+
post = Post.find(1) # issues GET http://blog.io/posts/1.json
|
266
|
+
comments = post.comments # issues GET http://blog.io/comments.json?post_id=1
|
267
|
+
```
|
268
|
+
|
269
|
+
In this case, the `Comment` model would have to be implemented as Active Resource, too.
|
270
|
+
|
271
|
+
If you control the server, you may wish to include nested resources thus avoiding a
|
272
|
+
second network request. Given the resource above, if the response includes comments
|
273
|
+
in the response, they will be automatically loaded into the Active Resource object.
|
274
|
+
The server-side model can be adjusted as follows to include comments in the response.
|
275
|
+
|
276
|
+
```ruby
|
277
|
+
class Post < ActiveRecord::Base
|
278
|
+
has_many :comments
|
279
|
+
|
280
|
+
def as_json(options)
|
281
|
+
super.merge(:include=>[:comments])
|
282
|
+
end
|
283
|
+
end
|
284
|
+
```
|
285
|
+
|
286
|
+
### Logging
|
287
|
+
|
288
|
+
Active Resource instruments the event `request.active_resource` when doing a request
|
289
|
+
to the remote service. You can subscribe to it by doing:
|
290
|
+
|
291
|
+
```ruby
|
292
|
+
ActiveSupport::Notifications.subscribe('request.active_resource') do |name, start, finish, id, payload|
|
293
|
+
```
|
294
|
+
|
295
|
+
The `payload` is a `Hash` with the following keys:
|
296
|
+
|
297
|
+
* `method` as a `Symbol`
|
298
|
+
* `request_uri` as a `String`
|
299
|
+
* `result` as an `Net::HTTPResponse`
|
300
|
+
|
301
|
+
## License
|
302
|
+
|
303
|
+
Active Resource is released under the MIT license:
|
304
|
+
|
305
|
+
* http://www.opensource.org/licenses/MIT
|
306
|
+
|
307
|
+
## Contributing to Active Resource
|
308
|
+
|
309
|
+
Active Resource is work of many contributors. You're encouraged to submit pull requests, propose
|
310
|
+
features and discuss issues.
|
311
|
+
|
312
|
+
See [CONTRIBUTING](https://github.com/rails/activeresource/blob/main/CONTRIBUTING.md).
|
313
|
+
|
314
|
+
## Support
|
315
|
+
|
316
|
+
Full API documentation is available at
|
317
|
+
|
318
|
+
* http://rubydoc.info/gems/activeresource
|
319
|
+
|
320
|
+
Bug reports and feature requests can be filed with the rest for the Ruby on Rails project here:
|
321
|
+
|
322
|
+
* https://github.com/rails/activeresource/issues
|
323
|
+
|
324
|
+
You can find more usage information in the ActiveResource::Base documentation.
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActiveResource::Associations::Builder
|
4
|
-
class Association
|
4
|
+
class Association # :nodoc:
|
5
5
|
# providing a Class-Variable, which will have a different store of subclasses
|
6
6
|
class_attribute :valid_options
|
7
7
|
self.valid_options = [:class_name]
|
@@ -25,7 +25,6 @@ module ActiveResource::Associations::Builder
|
|
25
25
|
end
|
26
26
|
|
27
27
|
private
|
28
|
-
|
29
28
|
def validate_options
|
30
29
|
options.assert_valid_keys(self.class.valid_options)
|
31
30
|
end
|
@@ -148,7 +148,7 @@ module ActiveResource::Associations
|
|
148
148
|
elsif attributes.include?(method_name)
|
149
149
|
attributes[method_name]
|
150
150
|
elsif !new_record?
|
151
|
-
instance_variable_set(ivar_name, reflection.klass.find(:all, params: {
|
151
|
+
instance_variable_set(ivar_name, reflection.klass.find(:all, params: { "#{self.class.element_name}_id": self.id }))
|
152
152
|
else
|
153
153
|
instance_variable_set(ivar_name, self.class.collection_parser.new)
|
154
154
|
end
|
@@ -166,7 +166,7 @@ module ActiveResource::Associations
|
|
166
166
|
elsif attributes.include?(method_name)
|
167
167
|
attributes[method_name]
|
168
168
|
elsif reflection.klass.respond_to?(:singleton_name)
|
169
|
-
instance_variable_set(ivar_name, reflection.klass.find(params: {
|
169
|
+
instance_variable_set(ivar_name, reflection.klass.find(params: { "#{self.class.element_name}_id": self.id }))
|
170
170
|
else
|
171
171
|
instance_variable_set(ivar_name, reflection.klass.find(:one, from: "/#{self.class.collection_name}/#{self.id}/#{method_name}#{self.class.format_extension}"))
|
172
172
|
end
|
data/lib/active_resource/base.rb
CHANGED
@@ -13,7 +13,6 @@ require "active_support/core_ext/object/duplicable"
|
|
13
13
|
require "set"
|
14
14
|
require "uri"
|
15
15
|
|
16
|
-
require "active_support/core_ext/uri"
|
17
16
|
require "active_resource/connection"
|
18
17
|
require "active_resource/formats"
|
19
18
|
require "active_resource/schema"
|
@@ -127,18 +126,25 @@ module ActiveResource
|
|
127
126
|
# requests. These sensitive credentials are sent unencrypted, visible to
|
128
127
|
# any onlooker, so this scheme should only be used with SSL.
|
129
128
|
#
|
130
|
-
# Digest authentication sends a
|
129
|
+
# Digest authentication sends a cryptographic hash of the username, password,
|
131
130
|
# HTTP method, URI, and a single-use secret key provided by the server.
|
132
131
|
# Sensitive credentials aren't visible to onlookers, so digest authentication
|
133
132
|
# doesn't require SSL. However, this doesn't mean the connection is secure!
|
134
133
|
# Just the username and password.
|
135
134
|
#
|
135
|
+
# Another common way to authenticate requests is via bearer tokens, a scheme
|
136
|
+
# originally created as part of the OAuth 2.0 protocol (see RFC 6750).
|
137
|
+
#
|
138
|
+
# Bearer authentication sends a token, that can maybe only be a short string
|
139
|
+
# of hexadecimal characters or even a JWT Token. Similarly to the Basic
|
140
|
+
# authentication, this scheme should only be used with SSL.
|
141
|
+
#
|
136
142
|
# (You really, really want to use SSL. There's little reason not to.)
|
137
143
|
#
|
138
144
|
# === Picking an authentication scheme
|
139
145
|
#
|
140
|
-
# Basic authentication is the default. To switch to digest authentication,
|
141
|
-
# set +auth_type+ to +:digest+:
|
146
|
+
# Basic authentication is the default. To switch to digest or bearer token authentication,
|
147
|
+
# set +auth_type+ to +:digest+ or +:bearer+:
|
142
148
|
#
|
143
149
|
# class Person < ActiveResource::Base
|
144
150
|
# self.auth_type = :digest
|
@@ -157,6 +163,16 @@ module ActiveResource
|
|
157
163
|
# self.site = "https://ryan:password@api.people.com"
|
158
164
|
# end
|
159
165
|
#
|
166
|
+
# === Setting the bearer token
|
167
|
+
#
|
168
|
+
# Set +bearer_token+ on the class:
|
169
|
+
#
|
170
|
+
# class Person < ActiveResource::Base
|
171
|
+
# # Set bearer token directly:
|
172
|
+
# self.auth_type = :bearer
|
173
|
+
# self.bearer_token = "my-bearer-token"
|
174
|
+
# end
|
175
|
+
#
|
160
176
|
# === Certificate Authentication
|
161
177
|
#
|
162
178
|
# You can also authenticate using an X509 certificate. <tt>See ssl_options=</tt> for all options.
|
@@ -202,7 +218,9 @@ module ActiveResource
|
|
202
218
|
# * 405 - ActiveResource::MethodNotAllowed
|
203
219
|
# * 409 - ActiveResource::ResourceConflict
|
204
220
|
# * 410 - ActiveResource::ResourceGone
|
221
|
+
# * 412 - ActiveResource::PreconditionFailed
|
205
222
|
# * 422 - ActiveResource::ResourceInvalid (rescued by save as validation errors)
|
223
|
+
# * 429 - ActiveResource::TooManyRequests
|
206
224
|
# * 401..499 - ActiveResource::ClientError
|
207
225
|
# * 500..599 - ActiveResource::ServerError
|
208
226
|
# * Other - ActiveResource::ConnectionError
|
@@ -319,7 +337,7 @@ module ActiveResource
|
|
319
337
|
|
320
338
|
class << self
|
321
339
|
include ThreadsafeAttributes
|
322
|
-
threadsafe_attribute :_headers, :_connection, :_user, :_password, :_site, :_proxy
|
340
|
+
threadsafe_attribute :_headers, :_connection, :_user, :_password, :_bearer_token, :_site, :_proxy
|
323
341
|
|
324
342
|
# Creates a schema for this resource - setting the attributes that are
|
325
343
|
# known prior to fetching an instance from the remote system.
|
@@ -407,7 +425,7 @@ module ActiveResource
|
|
407
425
|
# example:
|
408
426
|
#
|
409
427
|
# class Person < ActiveResource::Base
|
410
|
-
# schema = {'name' => :string, 'age' => :integer }
|
428
|
+
# self.schema = {'name' => :string, 'age' => :integer }
|
411
429
|
# end
|
412
430
|
#
|
413
431
|
# The keys/values can be strings or symbols. They will be converted to
|
@@ -472,8 +490,8 @@ module ActiveResource
|
|
472
490
|
self._site = nil
|
473
491
|
else
|
474
492
|
self._site = create_site_uri_from(site)
|
475
|
-
self._user = URI.
|
476
|
-
self._password = URI.
|
493
|
+
self._user = URI::DEFAULT_PARSER.unescape(_site.user) if _site.user
|
494
|
+
self._password = URI::DEFAULT_PARSER.unescape(_site.password) if _site.password
|
477
495
|
end
|
478
496
|
end
|
479
497
|
|
@@ -525,6 +543,22 @@ module ActiveResource
|
|
525
543
|
self._password = password
|
526
544
|
end
|
527
545
|
|
546
|
+
# Gets the \bearer_token for REST HTTP authentication.
|
547
|
+
def bearer_token
|
548
|
+
# Not using superclass_delegating_reader. See +site+ for explanation
|
549
|
+
if _bearer_token_defined?
|
550
|
+
_bearer_token
|
551
|
+
elsif superclass != Object && superclass.bearer_token
|
552
|
+
superclass.bearer_token.dup.freeze
|
553
|
+
end
|
554
|
+
end
|
555
|
+
|
556
|
+
# Sets the \bearer_token for REST HTTP authentication.
|
557
|
+
def bearer_token=(bearer_token)
|
558
|
+
self._connection = nil
|
559
|
+
self._bearer_token = bearer_token
|
560
|
+
end
|
561
|
+
|
528
562
|
def auth_type
|
529
563
|
if defined?(@auth_type)
|
530
564
|
@auth_type
|
@@ -649,6 +683,7 @@ module ActiveResource
|
|
649
683
|
_connection.proxy = proxy if proxy
|
650
684
|
_connection.user = user if user
|
651
685
|
_connection.password = password if password
|
686
|
+
_connection.bearer_token = bearer_token if bearer_token
|
652
687
|
_connection.auth_type = auth_type if auth_type
|
653
688
|
_connection.timeout = timeout if timeout
|
654
689
|
_connection.open_timeout = open_timeout if open_timeout
|
@@ -661,11 +696,10 @@ module ActiveResource
|
|
661
696
|
end
|
662
697
|
|
663
698
|
def headers
|
664
|
-
|
665
|
-
|
666
|
-
self._headers = superclass.headers.merge(headers_state)
|
699
|
+
self._headers ||= if superclass != Object
|
700
|
+
InheritingHash.new(superclass.headers)
|
667
701
|
else
|
668
|
-
|
702
|
+
{}
|
669
703
|
end
|
670
704
|
end
|
671
705
|
|
@@ -716,7 +750,7 @@ module ActiveResource
|
|
716
750
|
# Default value is <tt>site.path</tt>.
|
717
751
|
def prefix=(value = "/")
|
718
752
|
# Replace :placeholders with '#{embedded options[:lookups]}'
|
719
|
-
prefix_call = value.gsub(/:\w+/) { |key| "\#{URI.
|
753
|
+
prefix_call = value.gsub(/:\w+/) { |key| "\#{URI::DEFAULT_PARSER.escape options[#{key}].to_s}" }
|
720
754
|
|
721
755
|
# Clear prefix parameters in case they have been cached
|
722
756
|
@prefix_parameters = nil
|
@@ -733,10 +767,10 @@ module ActiveResource
|
|
733
767
|
raise
|
734
768
|
end
|
735
769
|
|
736
|
-
alias_method :set_prefix, :prefix=
|
770
|
+
alias_method :set_prefix, :prefix= # :nodoc:
|
737
771
|
|
738
|
-
alias_method :set_element_name, :element_name=
|
739
|
-
alias_method :set_collection_name, :collection_name=
|
772
|
+
alias_method :set_element_name, :element_name= # :nodoc:
|
773
|
+
alias_method :set_collection_name, :collection_name= # :nodoc:
|
740
774
|
|
741
775
|
def format_extension
|
742
776
|
include_format_in_path ? ".#{format.extension}" : ""
|
@@ -852,7 +886,7 @@ module ActiveResource
|
|
852
886
|
"#{prefix(prefix_options)}#{collection_name}#{format_extension}#{query_string(query_options)}"
|
853
887
|
end
|
854
888
|
|
855
|
-
alias_method :set_primary_key, :primary_key=
|
889
|
+
alias_method :set_primary_key, :primary_key= # :nodoc:
|
856
890
|
|
857
891
|
# Builds a new, unsaved record using the default values from the remote server so
|
858
892
|
# that it can be used with RESTful forms.
|
@@ -1050,7 +1084,6 @@ module ActiveResource
|
|
1050
1084
|
end
|
1051
1085
|
|
1052
1086
|
private
|
1053
|
-
|
1054
1087
|
def check_prefix_options(prefix_options)
|
1055
1088
|
p_options = HashWithIndifferentAccess.new(prefix_options)
|
1056
1089
|
prefix_parameters.each do |p|
|
@@ -1060,23 +1093,26 @@ module ActiveResource
|
|
1060
1093
|
|
1061
1094
|
# Find every resource
|
1062
1095
|
def find_every(options)
|
1063
|
-
|
1096
|
+
params = options[:params]
|
1097
|
+
prefix_options, query_options = split_options(params)
|
1098
|
+
|
1099
|
+
response =
|
1064
1100
|
case from = options[:from]
|
1065
1101
|
when Symbol
|
1066
|
-
|
1102
|
+
get(from, params)
|
1067
1103
|
when String
|
1068
|
-
path = "#{from}#{query_string(
|
1069
|
-
|
1104
|
+
path = "#{from}#{query_string(query_options)}"
|
1105
|
+
format.decode(connection.get(path, headers).body)
|
1070
1106
|
else
|
1071
|
-
prefix_options, query_options = split_options(options[:params])
|
1072
1107
|
path = collection_path(prefix_options, query_options)
|
1073
|
-
|
1108
|
+
format.decode(connection.get(path, headers).body)
|
1074
1109
|
end
|
1075
|
-
|
1076
|
-
|
1077
|
-
|
1078
|
-
|
1079
|
-
|
1110
|
+
|
1111
|
+
instantiate_collection(response || [], query_options, prefix_options)
|
1112
|
+
rescue ActiveResource::ResourceNotFound
|
1113
|
+
# Swallowing ResourceNotFound exceptions and return nil - as per
|
1114
|
+
# ActiveRecord.
|
1115
|
+
nil
|
1080
1116
|
end
|
1081
1117
|
|
1082
1118
|
# Find a single resource from a one-off URL
|
@@ -1145,8 +1181,8 @@ module ActiveResource
|
|
1145
1181
|
end
|
1146
1182
|
end
|
1147
1183
|
|
1148
|
-
attr_accessor :attributes
|
1149
|
-
attr_accessor :prefix_options
|
1184
|
+
attr_accessor :attributes # :nodoc:
|
1185
|
+
attr_accessor :prefix_options # :nodoc:
|
1150
1186
|
|
1151
1187
|
# If no schema has been defined for the class (see
|
1152
1188
|
# <tt>ActiveResource::schema=</tt>), the default automatic schema is
|
@@ -1203,7 +1239,7 @@ module ActiveResource
|
|
1203
1239
|
# not_ryan.hash # => {:not => "an ARes instance"}
|
1204
1240
|
def clone
|
1205
1241
|
# Clone all attributes except the pk and any nested ARes
|
1206
|
-
cloned =
|
1242
|
+
cloned = attributes.reject { |k, v| k == self.class.primary_key || v.is_a?(ActiveResource::Base) }.transform_values { |v| v.clone }
|
1207
1243
|
# Form the new resource - bypass initialize of resource with 'new' as that will call 'load' which
|
1208
1244
|
# attempts to convert hashes into member objects and arrays into collections of objects. We want
|
1209
1245
|
# the raw objects to be cloned so we bypass load by directly setting the attributes hash.
|
@@ -1589,7 +1625,6 @@ module ActiveResource
|
|
1589
1625
|
end
|
1590
1626
|
|
1591
1627
|
private
|
1592
|
-
|
1593
1628
|
# Determine whether the response is allowed to have a body per HTTP 1.1 spec section 4.4.1
|
1594
1629
|
def response_code_allows_body?(c)
|
1595
1630
|
!((100..199).include?(c) || [204, 304].include?(c))
|
@@ -1651,9 +1686,11 @@ module ActiveResource
|
|
1651
1686
|
|
1652
1687
|
# Create and return a class definition for a resource inside the current resource
|
1653
1688
|
def create_resource_for(resource_name)
|
1654
|
-
resource =
|
1689
|
+
resource = Class.new(ActiveResource::Base)
|
1655
1690
|
resource.prefix = self.class.prefix
|
1656
|
-
resource.site
|
1691
|
+
resource.site = self.class.site
|
1692
|
+
self.class.const_set(resource_name, resource)
|
1693
|
+
|
1657
1694
|
resource
|
1658
1695
|
end
|
1659
1696
|
|
@@ -1661,7 +1698,7 @@ module ActiveResource
|
|
1661
1698
|
self.class.__send__(:split_options, options)
|
1662
1699
|
end
|
1663
1700
|
|
1664
|
-
def method_missing(method_symbol, *arguments)
|
1701
|
+
def method_missing(method_symbol, *arguments) # :nodoc:
|
1665
1702
|
method_name = method_symbol.to_s
|
1666
1703
|
|
1667
1704
|
if method_name =~ /(=|\?)$/
|
@@ -5,7 +5,7 @@ require "active_support/inflector"
|
|
5
5
|
|
6
6
|
module ActiveResource # :nodoc:
|
7
7
|
class Collection # :nodoc:
|
8
|
-
SELF_DEFINE_METHODS = [:to_a, :collect!, :map
|
8
|
+
SELF_DEFINE_METHODS = [:to_a, :collect!, :map!, :all?]
|
9
9
|
include Enumerable
|
10
10
|
delegate :to_yaml, :all?, *(Array.instance_methods(false) - SELF_DEFINE_METHODS), to: :to_a
|
11
11
|
|
@@ -15,7 +15,7 @@ module ActiveResource # :nodoc:
|
|
15
15
|
# ActiveResource::Collection is a wrapper to handle parsing index responses that
|
16
16
|
# do not directly map to Rails conventions.
|
17
17
|
#
|
18
|
-
# You can define a custom class that
|
18
|
+
# You can define a custom class that inherits from ActiveResource::Collection
|
19
19
|
# in order to to set the elements instance.
|
20
20
|
#
|
21
21
|
# GET /posts.json delivers following response body:
|