activeresource 2.3.18 → 3.0.0.beta
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activeresource might be problematic. Click here for more details.
- data/CHANGELOG +1 -29
- data/README +7 -7
- data/examples/simple.rb +15 -0
- data/lib/active_resource.rb +17 -17
- data/lib/active_resource/base.rb +320 -66
- data/lib/active_resource/connection.rb +100 -100
- data/lib/active_resource/custom_methods.rb +33 -36
- data/lib/active_resource/exceptions.rb +4 -1
- data/lib/active_resource/formats.rb +4 -4
- data/lib/active_resource/formats/json_format.rb +2 -0
- data/lib/active_resource/formats/xml_format.rb +2 -0
- data/lib/active_resource/http_mock.rb +12 -103
- data/lib/active_resource/observing.rb +21 -0
- data/lib/active_resource/railtie.rb +17 -0
- data/lib/active_resource/railties/subscriber.rb +15 -0
- data/lib/active_resource/schema.rb +55 -0
- data/lib/active_resource/validations.rb +66 -215
- data/lib/active_resource/version.rb +3 -3
- metadata +29 -43
- data/Rakefile +0 -137
- data/lib/activeresource.rb +0 -2
- data/test/abstract_unit.rb +0 -21
- data/test/authorization_test.rb +0 -122
- data/test/base/custom_methods_test.rb +0 -100
- data/test/base/equality_test.rb +0 -52
- data/test/base/load_test.rb +0 -161
- data/test/base_errors_test.rb +0 -98
- data/test/base_test.rb +0 -1087
- data/test/connection_test.rb +0 -238
- data/test/fixtures/beast.rb +0 -14
- data/test/fixtures/customer.rb +0 -3
- data/test/fixtures/person.rb +0 -3
- data/test/fixtures/proxy.rb +0 -4
- data/test/fixtures/street_address.rb +0 -4
- data/test/format_test.rb +0 -112
- data/test/http_mock_test.rb +0 -155
- data/test/setter_trap.rb +0 -26
data/CHANGELOG
CHANGED
@@ -1,27 +1,4 @@
|
|
1
|
-
*
|
2
|
-
*2.3.10 (October 15, 2010)*
|
3
|
-
*2.3.9 (September 4, 2010)*
|
4
|
-
*2.3.8 (May 24, 2010)*
|
5
|
-
*2.3.7 (May 24, 2010)*
|
6
|
-
|
7
|
-
* Version bump.
|
8
|
-
|
9
|
-
|
10
|
-
*2.3.6 (May 23, 2010)*
|
11
|
-
|
12
|
-
* No changes, just a version bump.
|
13
|
-
|
14
|
-
|
15
|
-
*2.3.5 (November 25, 2009)*
|
16
|
-
|
17
|
-
* Minor Bug Fixes and deprecation warnings
|
18
|
-
|
19
|
-
* More flexible content type handling when parsing responses.
|
20
|
-
|
21
|
-
Ensures that ARes will handle responses like test/xml, or content types
|
22
|
-
with charsets included.
|
23
|
-
|
24
|
-
*2.3.4 (September 4, 2009)*
|
1
|
+
*Edge*
|
25
2
|
|
26
3
|
* Add support for errors in JSON format. #1956 [Fabien Jakimowicz]
|
27
4
|
|
@@ -32,11 +9,6 @@
|
|
32
9
|
* HTTP proxy support. #2133 [Marshall Huss, Sébastien Dabet]
|
33
10
|
|
34
11
|
|
35
|
-
*2.3.3 (July 12, 2009)*
|
36
|
-
|
37
|
-
* No changes, just a version bump.
|
38
|
-
|
39
|
-
|
40
12
|
*2.3.2 [Final] (March 15, 2009)*
|
41
13
|
|
42
14
|
* Nothing new, just included in 2.3.2
|
data/README
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
= Active Resource
|
2
2
|
|
3
3
|
Active Resource (ARes) connects business objects and Representational State Transfer (REST)
|
4
|
-
web services. It implements object-relational mapping for REST
|
4
|
+
web services. It implements object-relational mapping for REST web services to provide transparent
|
5
5
|
proxying capabilities between a client (ActiveResource) and a RESTful service (which is provided by Simply RESTful routing
|
6
6
|
in ActionController::Resources).
|
7
7
|
|
@@ -22,14 +22,14 @@ received and serialized into a usable Ruby object.
|
|
22
22
|
|
23
23
|
=== Configuration and Usage
|
24
24
|
|
25
|
-
Putting
|
25
|
+
Putting Active Resource to use is very similar to Active Record. It's as simple as creating a model class
|
26
26
|
that inherits from ActiveResource::Base and providing a <tt>site</tt> class variable to it:
|
27
27
|
|
28
28
|
class Person < ActiveResource::Base
|
29
29
|
self.site = "http://api.people.com:3000/"
|
30
30
|
end
|
31
31
|
|
32
|
-
Now the Person class is REST enabled and can invoke REST services very similarly to how
|
32
|
+
Now the Person class is REST enabled and can invoke REST services very similarly to how Active Record invokes
|
33
33
|
lifecycle methods that operate against a persistent store.
|
34
34
|
|
35
35
|
# Find a person with id = 1
|
@@ -42,7 +42,7 @@ records. But rather than dealing directly with a database record, you're dealin
|
|
42
42
|
==== Protocol
|
43
43
|
|
44
44
|
Active Resource is built on a standard XML format for requesting and submitting resources over HTTP. It mirrors the RESTful routing
|
45
|
-
built into
|
45
|
+
built into Action Controller but will also work with any other REST service that properly implements the protocol.
|
46
46
|
REST uses HTTP, but unlike "typical" web applications, it makes use of all the verbs available in the HTTP specification:
|
47
47
|
|
48
48
|
* GET requests are used for finding and retrieving resources.
|
@@ -55,8 +55,8 @@ for more general information on REST web services, see the article here[http://e
|
|
55
55
|
|
56
56
|
==== Find
|
57
57
|
|
58
|
-
GET
|
59
|
-
for a request for a single element
|
58
|
+
Find requests use the GET method and expect the XML form of whatever resource/resources is/are being requested. So,
|
59
|
+
for a request for a single element, the XML of that item is expected in response:
|
60
60
|
|
61
61
|
# Expects a response of
|
62
62
|
#
|
@@ -101,7 +101,7 @@ Collections can also be requested in a similar fashion
|
|
101
101
|
|
102
102
|
==== Create
|
103
103
|
|
104
|
-
Creating a new resource submits the
|
104
|
+
Creating a new resource submits the XML form of the resource as the body of the request and expects
|
105
105
|
a 'Location' header in the response with the RESTful URL location of the newly created resource. The
|
106
106
|
id of the newly created resource is parsed out of the Location response header and automatically set
|
107
107
|
as the id of the ARes object.
|
data/examples/simple.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
$LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib"
|
2
|
+
require 'active_resource'
|
3
|
+
require 'active_support/core_ext/hash/conversions'
|
4
|
+
|
5
|
+
ActiveSupport::XmlMini.backend = ENV['XMLMINI'] || 'REXML'
|
6
|
+
ActiveResource::HttpMock.respond_to do |mock|
|
7
|
+
mock.get '/people/1.xml', {}, { :id => 1, :name => 'bob' }.to_xml(:root => 'person')
|
8
|
+
end
|
9
|
+
|
10
|
+
class Person < ActiveResource::Base
|
11
|
+
self.site = 'http://localhost/'
|
12
|
+
end
|
13
|
+
|
14
|
+
bob = Person.find(1)
|
15
|
+
puts bob.inspect
|
data/lib/active_resource.rb
CHANGED
@@ -21,24 +21,24 @@
|
|
21
21
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
22
|
#++
|
23
23
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
$:.unshift activesupport_path
|
30
|
-
require 'active_support'
|
31
|
-
end
|
32
|
-
end
|
24
|
+
activesupport_path = File.expand_path('../../../activesupport/lib', __FILE__)
|
25
|
+
$:.unshift(activesupport_path) if File.directory?(activesupport_path) && !$:.include?(activesupport_path)
|
26
|
+
|
27
|
+
activemodel_path = File.expand_path('../../../activemodel/lib', __FILE__)
|
28
|
+
$:.unshift(activemodel_path) if File.directory?(activemodel_path) && !$:.include?(activemodel_path)
|
33
29
|
|
34
|
-
require '
|
35
|
-
require '
|
36
|
-
require 'active_resource/validations'
|
37
|
-
require 'active_resource/custom_methods'
|
30
|
+
require 'active_support'
|
31
|
+
require 'active_model'
|
38
32
|
|
39
33
|
module ActiveResource
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
34
|
+
extend ActiveSupport::Autoload
|
35
|
+
|
36
|
+
autoload :Base
|
37
|
+
autoload :Connection
|
38
|
+
autoload :CustomMethods
|
39
|
+
autoload :Formats
|
40
|
+
autoload :HttpMock
|
41
|
+
autoload :Observing
|
42
|
+
autoload :Schema
|
43
|
+
autoload :Validations
|
44
44
|
end
|
data/lib/active_resource/base.rb
CHANGED
@@ -1,6 +1,21 @@
|
|
1
|
-
require '
|
2
|
-
require '
|
1
|
+
require 'active_support'
|
2
|
+
require 'active_support/core_ext/class/attribute_accessors'
|
3
|
+
require 'active_support/core_ext/class/inheritable_attributes'
|
4
|
+
require 'active_support/core_ext/hash/indifferent_access'
|
5
|
+
require 'active_support/core_ext/kernel/reporting'
|
6
|
+
require 'active_support/core_ext/module/attr_accessor_with_default'
|
7
|
+
require 'active_support/core_ext/module/delegation'
|
8
|
+
require 'active_support/core_ext/module/aliasing'
|
9
|
+
require 'active_support/core_ext/object/blank'
|
10
|
+
require 'active_support/core_ext/object/misc'
|
11
|
+
require 'active_support/core_ext/object/to_query'
|
3
12
|
require 'set'
|
13
|
+
require 'uri'
|
14
|
+
|
15
|
+
require 'active_resource/exceptions'
|
16
|
+
require 'active_resource/connection'
|
17
|
+
require 'active_resource/formats'
|
18
|
+
require 'active_resource/schema'
|
4
19
|
|
5
20
|
module ActiveResource
|
6
21
|
# ActiveResource::Base is the main class for mapping RESTful resources as models in a Rails application.
|
@@ -19,7 +34,7 @@ module ActiveResource
|
|
19
34
|
# end
|
20
35
|
#
|
21
36
|
# Now the Person class is mapped to RESTful resources located at <tt>http://api.people.com:3000/people/</tt>, and
|
22
|
-
# you can now use Active Resource's
|
37
|
+
# you can now use Active Resource's lifecycle methods to manipulate resources. In the case where you already have
|
23
38
|
# an existing model with the same name as the desired RESTful resource you can set the +element_name+ value.
|
24
39
|
#
|
25
40
|
# class PersonResource < ActiveResource::Base
|
@@ -27,6 +42,13 @@ module ActiveResource
|
|
27
42
|
# self.element_name = "person"
|
28
43
|
# end
|
29
44
|
#
|
45
|
+
# If your Active Resource object is required to use an HTTP proxy you can set the +proxy+ value which holds a URI.
|
46
|
+
#
|
47
|
+
# class PersonResource < ActiveResource::Base
|
48
|
+
# self.site = "http://api.people.com:3000/"
|
49
|
+
# self.proxy = "http://user:password@proxy.people.com:8080"
|
50
|
+
# end
|
51
|
+
#
|
30
52
|
#
|
31
53
|
# == Lifecycle methods
|
32
54
|
#
|
@@ -127,6 +149,7 @@ module ActiveResource
|
|
127
149
|
# :verify_mode => OpenSSL::SSL::VERIFY_PEER}
|
128
150
|
# end
|
129
151
|
#
|
152
|
+
#
|
130
153
|
# == Errors & Validation
|
131
154
|
#
|
132
155
|
# Error handling and validation is handled in much the same manner as you're used to seeing in
|
@@ -144,7 +167,7 @@ module ActiveResource
|
|
144
167
|
#
|
145
168
|
# <tt>404</tt> is just one of the HTTP error response codes that Active Resource will handle with its own exception. The
|
146
169
|
# following HTTP response codes will also result in these exceptions:
|
147
|
-
#
|
170
|
+
#
|
148
171
|
# * 200..399 - Valid response, no exception (other than 301, 302)
|
149
172
|
# * 301, 302 - ActiveResource::Redirection
|
150
173
|
# * 400 - ActiveResource::BadRequest
|
@@ -172,7 +195,7 @@ module ActiveResource
|
|
172
195
|
#
|
173
196
|
# === Validation errors
|
174
197
|
#
|
175
|
-
# Active Resource supports validations on resources and will return errors if any these validations fail
|
198
|
+
# Active Resource supports validations on resources and will return errors if any of these validations fail
|
176
199
|
# (e.g., "First name can not be blank" and so on). These types of errors are denoted in the response by
|
177
200
|
# a response code of <tt>422</tt> and an XML or JSON representation of the validation errors. The save operation will
|
178
201
|
# then fail (with a <tt>false</tt> return value) and the validation errors can be accessed on the resource in question.
|
@@ -227,10 +250,125 @@ module ActiveResource
|
|
227
250
|
# The logger for diagnosing and tracing Active Resource calls.
|
228
251
|
cattr_accessor :logger
|
229
252
|
|
230
|
-
# Controls the top-level behavior of JSON serialization
|
231
|
-
cattr_accessor :include_root_in_json, :instance_writer => false
|
232
|
-
|
233
253
|
class << self
|
254
|
+
# Creates a schema for this resource - setting the attributes that are
|
255
|
+
# known prior to fetching an instance from the remote system.
|
256
|
+
#
|
257
|
+
# The schema helps define the set of <tt>known_attributes</tt> of the
|
258
|
+
# current resource.
|
259
|
+
#
|
260
|
+
# There is no need to specify a schema for your Active Resource. If
|
261
|
+
# you do not, the <tt>known_attributes</tt> will be guessed from the
|
262
|
+
# instance attributes returned when an instance is fetched from the
|
263
|
+
# remote system.
|
264
|
+
#
|
265
|
+
# example:
|
266
|
+
# class Person < ActiveResource::Base
|
267
|
+
# schema do
|
268
|
+
# # define each attribute separately
|
269
|
+
# attribute 'name', :string
|
270
|
+
#
|
271
|
+
# # or use the convenience methods and pass >=1 attribute names
|
272
|
+
# string 'eye_colour', 'hair_colour'
|
273
|
+
# integer 'age'
|
274
|
+
# float 'height', 'weight'
|
275
|
+
#
|
276
|
+
# # unsupported types should be left as strings
|
277
|
+
# # overload the accessor methods if you need to convert them
|
278
|
+
# attribute 'created_at', 'string'
|
279
|
+
# end
|
280
|
+
# end
|
281
|
+
#
|
282
|
+
# p = Person.new
|
283
|
+
# p.respond_to? :name # => true
|
284
|
+
# p.respond_to? :age # => true
|
285
|
+
# p.name # => nil
|
286
|
+
# p.age # => nil
|
287
|
+
#
|
288
|
+
# j = Person.find_by_name('John') # <person><name>John</name><age>34</age><num_children>3</num_children></person>
|
289
|
+
# j.respond_to? :name # => true
|
290
|
+
# j.respond_to? :age # => true
|
291
|
+
# j.name # => 'John'
|
292
|
+
# j.age # => '34' # note this is a string!
|
293
|
+
# j.num_children # => '3' # note this is a string!
|
294
|
+
#
|
295
|
+
# p.num_children # => NoMethodError
|
296
|
+
#
|
297
|
+
# Attribute-types must be one of:
|
298
|
+
# string, integer, float
|
299
|
+
#
|
300
|
+
# Note: at present the attribute-type doesn't do anything, but stay
|
301
|
+
# tuned...
|
302
|
+
# Shortly it will also *cast* the value of the returned attribute.
|
303
|
+
# ie:
|
304
|
+
# j.age # => 34 # cast to an integer
|
305
|
+
# j.weight # => '65' # still a string!
|
306
|
+
#
|
307
|
+
def schema(&block)
|
308
|
+
if block_given?
|
309
|
+
schema_definition = Schema.new
|
310
|
+
schema_definition.instance_eval(&block)
|
311
|
+
|
312
|
+
# skip out if we didn't define anything
|
313
|
+
return unless schema_definition.attrs.present?
|
314
|
+
|
315
|
+
@schema ||= {}.with_indifferent_access
|
316
|
+
@known_attributes ||= []
|
317
|
+
|
318
|
+
schema_definition.attrs.each do |k,v|
|
319
|
+
@schema[k] = v
|
320
|
+
@known_attributes << k
|
321
|
+
end
|
322
|
+
|
323
|
+
schema
|
324
|
+
else
|
325
|
+
@schema ||= nil
|
326
|
+
end
|
327
|
+
end
|
328
|
+
|
329
|
+
# Alternative, direct way to specify a <tt>schema</tt> for this
|
330
|
+
# Resource. <tt>schema</tt> is more flexible, but this is quick
|
331
|
+
# for a very simple schema.
|
332
|
+
#
|
333
|
+
# Pass the schema as a hash with the keys being the attribute-names
|
334
|
+
# and the value being one of the accepted attribute types (as defined
|
335
|
+
# in <tt>schema</tt>)
|
336
|
+
#
|
337
|
+
# example:
|
338
|
+
#
|
339
|
+
# class Person < ActiveResource::Base
|
340
|
+
# schema = {'name' => :string, 'age' => :integer }
|
341
|
+
# end
|
342
|
+
#
|
343
|
+
# The keys/values can be strings or symbols. They will be converted to
|
344
|
+
# strings.
|
345
|
+
#
|
346
|
+
def schema=(the_schema)
|
347
|
+
unless the_schema.present?
|
348
|
+
# purposefully nulling out the schema
|
349
|
+
@schema = nil
|
350
|
+
@known_attributes = []
|
351
|
+
return
|
352
|
+
end
|
353
|
+
|
354
|
+
raise ArgumentError, "Expected a hash" unless the_schema.kind_of? Hash
|
355
|
+
|
356
|
+
schema do
|
357
|
+
the_schema.each {|k,v| attribute(k,v) }
|
358
|
+
end
|
359
|
+
end
|
360
|
+
|
361
|
+
# Returns the list of known attributes for this resource, gathered
|
362
|
+
# from the provided <tt>schema</tt>
|
363
|
+
# Attributes that are known will cause your resource to return 'true'
|
364
|
+
# when <tt>respond_to?</tt> is called on them. A known attribute will
|
365
|
+
# return nil if not set (rather than <t>MethodNotFound</tt>); thus
|
366
|
+
# known attributes can be used with <tt>validates_presence_of</tt>
|
367
|
+
# without a getter-method.
|
368
|
+
def known_attributes
|
369
|
+
@known_attributes ||= []
|
370
|
+
end
|
371
|
+
|
234
372
|
# Gets the URI of the REST resources to map for this class. The site variable is required for
|
235
373
|
# Active Resource's mapping to work.
|
236
374
|
def site
|
@@ -264,8 +402,8 @@ module ActiveResource
|
|
264
402
|
@site = nil
|
265
403
|
else
|
266
404
|
@site = create_site_uri_from(site)
|
267
|
-
@user =
|
268
|
-
@password =
|
405
|
+
@user = uri_parser.unescape(@site.user) if @site.user
|
406
|
+
@password = uri_parser.unescape(@site.password) if @site.password
|
269
407
|
end
|
270
408
|
end
|
271
409
|
|
@@ -317,6 +455,17 @@ module ActiveResource
|
|
317
455
|
@password = password
|
318
456
|
end
|
319
457
|
|
458
|
+
def auth_type
|
459
|
+
if defined?(@auth_type)
|
460
|
+
@auth_type
|
461
|
+
end
|
462
|
+
end
|
463
|
+
|
464
|
+
def auth_type=(auth_type)
|
465
|
+
@connection = nil
|
466
|
+
@auth_type = auth_type
|
467
|
+
end
|
468
|
+
|
320
469
|
# Sets the format that attributes are sent and received in from a mime type reference:
|
321
470
|
#
|
322
471
|
# Person.format = :json
|
@@ -336,7 +485,7 @@ module ActiveResource
|
|
336
485
|
|
337
486
|
# Returns the current format, default is ActiveResource::Formats::XmlFormat.
|
338
487
|
def format
|
339
|
-
read_inheritable_attribute(:format) || ActiveResource::Formats
|
488
|
+
read_inheritable_attribute(:format) || ActiveResource::Formats::XmlFormat
|
340
489
|
end
|
341
490
|
|
342
491
|
# Sets the number of seconds after which requests to the REST API should time out.
|
@@ -388,6 +537,7 @@ module ActiveResource
|
|
388
537
|
@connection.proxy = proxy if proxy
|
389
538
|
@connection.user = user if user
|
390
539
|
@connection.password = password if password
|
540
|
+
@connection.auth_type = auth_type if auth_type
|
391
541
|
@connection.timeout = timeout if timeout
|
392
542
|
@connection.ssl_options = ssl_options if ssl_options
|
393
543
|
@connection
|
@@ -402,11 +552,11 @@ module ActiveResource
|
|
402
552
|
|
403
553
|
# Do not include any modules in the default element name. This makes it easier to seclude ARes objects
|
404
554
|
# in a separate namespace without having to set element_name repeatedly.
|
405
|
-
attr_accessor_with_default(:element_name) { to_s.split("::").last
|
555
|
+
attr_accessor_with_default(:element_name) { ActiveSupport::Inflector.underscore(to_s.split("::").last) } #:nodoc:
|
406
556
|
|
407
|
-
attr_accessor_with_default(:collection_name) {
|
557
|
+
attr_accessor_with_default(:collection_name) { ActiveSupport::Inflector.pluralize(element_name) } #:nodoc:
|
408
558
|
attr_accessor_with_default(:primary_key, 'id') #:nodoc:
|
409
|
-
|
559
|
+
|
410
560
|
# Gets the \prefix for a resource's nested URL (e.g., <tt>prefix/collectionname/1.xml</tt>)
|
411
561
|
# This method is regenerated at runtime based on what the \prefix is set to.
|
412
562
|
def prefix(options={})
|
@@ -434,13 +584,13 @@ module ActiveResource
|
|
434
584
|
@prefix_parameters = nil
|
435
585
|
|
436
586
|
# Redefine the new methods.
|
437
|
-
code
|
587
|
+
code = <<-end_code
|
438
588
|
def prefix_source() "#{value}" end
|
439
589
|
def prefix(options={}) "#{prefix_call}" end
|
440
590
|
end_code
|
441
|
-
silence_warnings { instance_eval code, __FILE__,
|
591
|
+
silence_warnings { instance_eval code, __FILE__, __LINE__ }
|
442
592
|
rescue
|
443
|
-
logger.error "Couldn't set prefix: #{$!}\n #{code}"
|
593
|
+
logger.error "Couldn't set prefix: #{$!}\n #{code}" if logger
|
444
594
|
raise
|
445
595
|
end
|
446
596
|
|
@@ -479,7 +629,7 @@ module ActiveResource
|
|
479
629
|
# will split from the +prefix_options+.
|
480
630
|
#
|
481
631
|
# ==== Options
|
482
|
-
# * +prefix_options+ - A hash to add a prefix to the request for nested
|
632
|
+
# * +prefix_options+ - A hash to add a prefix to the request for nested URLs (e.g., <tt>:account_id => 19</tt>
|
483
633
|
# would yield a URL like <tt>/accounts/19/purchases.xml</tt>).
|
484
634
|
# * +query_options+ - A hash to add items to the query string for the request.
|
485
635
|
#
|
@@ -577,6 +727,19 @@ module ActiveResource
|
|
577
727
|
#
|
578
728
|
# StreetAddress.find(1, :params => { :person_id => 1 })
|
579
729
|
# # => GET /people/1/street_addresses/1.xml
|
730
|
+
#
|
731
|
+
# == Failure or missing data
|
732
|
+
# A failure to find the requested object raises a ResourceNotFound
|
733
|
+
# exception if the find was called with an id.
|
734
|
+
# With any other scope, find returns nil when no data is returned.
|
735
|
+
#
|
736
|
+
# Person.find(1)
|
737
|
+
# # => raises ResourcenotFound
|
738
|
+
#
|
739
|
+
# Person.find(:all)
|
740
|
+
# Person.find(:first)
|
741
|
+
# Person.find(:last)
|
742
|
+
# # => nil
|
580
743
|
def find(*arguments)
|
581
744
|
scope = arguments.slice!(0)
|
582
745
|
options = arguments.slice!(0) || {}
|
@@ -590,6 +753,28 @@ module ActiveResource
|
|
590
753
|
end
|
591
754
|
end
|
592
755
|
|
756
|
+
|
757
|
+
# A convenience wrapper for <tt>find(:first, *args)</tt>. You can pass
|
758
|
+
# in all the same arguments to this method as you can to
|
759
|
+
# <tt>find(:first)</tt>.
|
760
|
+
def first(*args)
|
761
|
+
find(:first, *args)
|
762
|
+
end
|
763
|
+
|
764
|
+
# A convenience wrapper for <tt>find(:last, *args)</tt>. You can pass
|
765
|
+
# in all the same arguments to this method as you can to
|
766
|
+
# <tt>find(:last)</tt>.
|
767
|
+
def last(*args)
|
768
|
+
find(:last, *args)
|
769
|
+
end
|
770
|
+
|
771
|
+
# This is an alias for find(:all). You can pass in all the same
|
772
|
+
# arguments to this method as you can to <tt>find(:all)</tt>
|
773
|
+
def all(*args)
|
774
|
+
find(:all, *args)
|
775
|
+
end
|
776
|
+
|
777
|
+
|
593
778
|
# Deletes the resources with the ID in the +id+ parameter.
|
594
779
|
#
|
595
780
|
# ==== Options
|
@@ -630,16 +815,22 @@ module ActiveResource
|
|
630
815
|
private
|
631
816
|
# Find every resource
|
632
817
|
def find_every(options)
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
818
|
+
begin
|
819
|
+
case from = options[:from]
|
820
|
+
when Symbol
|
821
|
+
instantiate_collection(get(from, options[:params]))
|
822
|
+
when String
|
823
|
+
path = "#{from}#{query_string(options[:params])}"
|
824
|
+
instantiate_collection(connection.get(path, headers) || [])
|
825
|
+
else
|
826
|
+
prefix_options, query_options = split_options(options[:params])
|
827
|
+
path = collection_path(prefix_options, query_options)
|
828
|
+
instantiate_collection( (connection.get(path, headers) || []), prefix_options )
|
829
|
+
end
|
830
|
+
rescue ActiveResource::ResourceNotFound
|
831
|
+
# Swallowing ResourceNotFound exceptions and return nil - as per
|
832
|
+
# ActiveRecord.
|
833
|
+
nil
|
643
834
|
end
|
644
835
|
end
|
645
836
|
|
@@ -674,12 +865,12 @@ module ActiveResource
|
|
674
865
|
|
675
866
|
# Accepts a URI and creates the site URI from that.
|
676
867
|
def create_site_uri_from(site)
|
677
|
-
site.is_a?(URI) ? site.dup :
|
868
|
+
site.is_a?(URI) ? site.dup : uri_parser.parse(site)
|
678
869
|
end
|
679
870
|
|
680
871
|
# Accepts a URI and creates the proxy URI from that.
|
681
872
|
def create_proxy_uri_from(proxy)
|
682
|
-
proxy.is_a?(URI) ? proxy.dup :
|
873
|
+
proxy.is_a?(URI) ? proxy.dup : uri_parser.parse(proxy)
|
683
874
|
end
|
684
875
|
|
685
876
|
# contains a set of the current prefix parameters.
|
@@ -704,11 +895,30 @@ module ActiveResource
|
|
704
895
|
|
705
896
|
[ prefix_options, query_options ]
|
706
897
|
end
|
898
|
+
|
899
|
+
def uri_parser
|
900
|
+
@uri_parser ||= URI.const_defined?(:Parser) ? URI::Parser.new : URI
|
901
|
+
end
|
707
902
|
end
|
708
903
|
|
709
904
|
attr_accessor :attributes #:nodoc:
|
710
905
|
attr_accessor :prefix_options #:nodoc:
|
711
906
|
|
907
|
+
# If no schema has been defined for the class (see
|
908
|
+
# <tt>ActiveResource::schema=</tt>), the default automatic schema is
|
909
|
+
# generated from the current instance's attributes
|
910
|
+
def schema
|
911
|
+
self.class.schema || self.attributes
|
912
|
+
end
|
913
|
+
|
914
|
+
# This is a list of known attributes for this resource. Either
|
915
|
+
# gathered fromthe provided <tt>schema</tt>, or from the attributes
|
916
|
+
# set on this instance after it has been fetched from the remote system.
|
917
|
+
def known_attributes
|
918
|
+
self.class.known_attributes + self.attributes.keys.map(&:to_s)
|
919
|
+
end
|
920
|
+
|
921
|
+
|
712
922
|
# Constructor method for \new resources; the optional +attributes+ parameter takes a \hash
|
713
923
|
# of attributes for the \new resource.
|
714
924
|
#
|
@@ -721,7 +931,7 @@ module ActiveResource
|
|
721
931
|
# my_other_course = Course.new(:name => "Philosophy: Reason and Being", :lecturer => "Ralph Cling")
|
722
932
|
# my_other_course.save
|
723
933
|
def initialize(attributes = {})
|
724
|
-
@attributes = {}
|
934
|
+
@attributes = {}.with_indifferent_access
|
725
935
|
@prefix_options = {}
|
726
936
|
load(attributes)
|
727
937
|
end
|
@@ -762,7 +972,7 @@ module ActiveResource
|
|
762
972
|
end
|
763
973
|
|
764
974
|
|
765
|
-
#
|
975
|
+
# Returns +true+ if this object hasn't yet been saved, otherwise, returns +false+.
|
766
976
|
#
|
767
977
|
# ==== Examples
|
768
978
|
# not_new = Computer.create(:brand => 'Apple', :make => 'MacBook', :vendor => 'MacMall')
|
@@ -831,7 +1041,7 @@ module ActiveResource
|
|
831
1041
|
id.hash
|
832
1042
|
end
|
833
1043
|
|
834
|
-
#
|
1044
|
+
# Duplicates the current resource without saving it.
|
835
1045
|
#
|
836
1046
|
# ==== Examples
|
837
1047
|
# my_invoice = Invoice.create(:customer => 'That Company')
|
@@ -850,8 +1060,8 @@ module ActiveResource
|
|
850
1060
|
end
|
851
1061
|
end
|
852
1062
|
|
853
|
-
#
|
854
|
-
# +update+ if it
|
1063
|
+
# Saves (+POST+) or \updates (+PUT+) a resource. Delegates to +create+ if the object is \new,
|
1064
|
+
# +update+ if it exists. If the response to the \save includes a body, it will be assumed that this body
|
855
1065
|
# is XML for the final object as it looked after the \save (which would include attributes like +created_at+
|
856
1066
|
# that weren't part of the original submit).
|
857
1067
|
#
|
@@ -867,6 +1077,23 @@ module ActiveResource
|
|
867
1077
|
new? ? create : update
|
868
1078
|
end
|
869
1079
|
|
1080
|
+
# Saves the resource.
|
1081
|
+
#
|
1082
|
+
# If the resource is new, it is created via +POST+, otherwise the
|
1083
|
+
# existing resource is updated via +PUT+.
|
1084
|
+
#
|
1085
|
+
# With <tt>save!</tt> validations always run. If any of them fail
|
1086
|
+
# ActiveResource::ResourceInvalid gets raised, and nothing is POSTed to
|
1087
|
+
# the remote system.
|
1088
|
+
# See ActiveResource::Validations for more information.
|
1089
|
+
#
|
1090
|
+
# There's a series of callbacks associated with <tt>save!</tt>. If any
|
1091
|
+
# of the <tt>before_*</tt> callbacks return +false+ the action is
|
1092
|
+
# cancelled and <tt>save!</tt> raises ActiveResource::ResourceInvalid.
|
1093
|
+
def save!
|
1094
|
+
save || raise(ResourceInvalid.new(self))
|
1095
|
+
end
|
1096
|
+
|
870
1097
|
# Deletes the resource from the remote service.
|
871
1098
|
#
|
872
1099
|
# ==== Examples
|
@@ -903,7 +1130,7 @@ module ActiveResource
|
|
903
1130
|
!new? && self.class.exists?(to_param, :params => prefix_options)
|
904
1131
|
end
|
905
1132
|
|
906
|
-
|
1133
|
+
# Converts the resource to an XML string representation.
|
907
1134
|
#
|
908
1135
|
# ==== Options
|
909
1136
|
# The +options+ parameter is handed off to the +to_xml+ method on each
|
@@ -912,14 +1139,7 @@ module ActiveResource
|
|
912
1139
|
#
|
913
1140
|
# * <tt>:indent</tt> - Set the indent level for the XML output (default is +2+).
|
914
1141
|
# * <tt>:dasherize</tt> - Boolean option to determine whether or not element names should
|
915
|
-
# replace underscores with dashes
|
916
|
-
# by setting the module attribute <tt>ActiveSupport.dasherize_xml = false</tt> in an initializer. Because save
|
917
|
-
# uses this method, and there are no options on save, then you will have to set the default if you don't
|
918
|
-
# want underscores in element names to become dashes when the resource is saved. This is important when
|
919
|
-
# integrating with non-Rails applications.
|
920
|
-
# * <tt>:camelize</tt> - Boolean option to determine whether or not element names should be converted
|
921
|
-
# to camel case, e.g some_name to SomeName. Default is <tt>false</tt>. Like <tt>:dasherize</tt> you can
|
922
|
-
# change the default by setting the module attribute <tt>ActiveSupport.camelise_xml = true</tt> in an initializer.
|
1142
|
+
# replace underscores with dashes (default is <tt>false</tt>).
|
923
1143
|
# * <tt>:skip_instruct</tt> - Toggle skipping the +instruct!+ call on the XML builder
|
924
1144
|
# that generates the XML declaration (default is <tt>false</tt>).
|
925
1145
|
#
|
@@ -972,14 +1192,8 @@ module ActiveResource
|
|
972
1192
|
# applicable depend on the configured encoding format.
|
973
1193
|
def encode(options={})
|
974
1194
|
case self.class.format
|
975
|
-
when ActiveResource::Formats
|
1195
|
+
when ActiveResource::Formats::XmlFormat
|
976
1196
|
self.class.format.encode(attributes, {:root => self.class.element_name}.merge(options))
|
977
|
-
when ActiveResource::Formats::JsonFormat
|
978
|
-
if ActiveResource::Base.include_root_in_json
|
979
|
-
self.class.format.encode({self.class.element_name => attributes}, options)
|
980
|
-
else
|
981
|
-
self.class.format.encode(attributes, options)
|
982
|
-
end
|
983
1197
|
else
|
984
1198
|
self.class.format.encode(attributes, options)
|
985
1199
|
end
|
@@ -1046,6 +1260,36 @@ module ActiveResource
|
|
1046
1260
|
self
|
1047
1261
|
end
|
1048
1262
|
|
1263
|
+
# Updates a single attribute and then saves the object.
|
1264
|
+
#
|
1265
|
+
# Note: Unlike ActiveRecord::Base.update_attribute, this method <b>is</b>
|
1266
|
+
# subject to normal validation routines as an update sends the whole body
|
1267
|
+
# of the resource in the request. (See Validations).
|
1268
|
+
#
|
1269
|
+
# As such, this method is equivalent to calling update_attributes with a single attribute/value pair.
|
1270
|
+
#
|
1271
|
+
# If the saving fails because of a connection or remote service error, an
|
1272
|
+
# exception will be raised. If saving fails because the resource is
|
1273
|
+
# invalid then <tt>false</tt> will be returned.
|
1274
|
+
def update_attribute(name, value)
|
1275
|
+
self.send("#{name}=".to_sym, value)
|
1276
|
+
self.save
|
1277
|
+
end
|
1278
|
+
|
1279
|
+
# Updates this resource with all the attributes from the passed-in Hash
|
1280
|
+
# and requests that the record be saved.
|
1281
|
+
#
|
1282
|
+
# If the saving fails because of a connection or remote service error, an
|
1283
|
+
# exception will be raised. If saving fails because the resource is
|
1284
|
+
# invalid then <tt>false</tt> will be returned.
|
1285
|
+
#
|
1286
|
+
# Note: Though this request can be made with a partial set of the
|
1287
|
+
# resource's attributes, the full body of the request will still be sent
|
1288
|
+
# in the save request to the remote service.
|
1289
|
+
def update_attributes(attributes)
|
1290
|
+
load(attributes) && save
|
1291
|
+
end
|
1292
|
+
|
1049
1293
|
# For checking <tt>respond_to?</tt> without searching the attributes (which is faster).
|
1050
1294
|
alias_method :respond_to_without_attributes?, :respond_to?
|
1051
1295
|
|
@@ -1055,18 +1299,18 @@ module ActiveResource
|
|
1055
1299
|
def respond_to?(method, include_priv = false)
|
1056
1300
|
method_name = method.to_s
|
1057
1301
|
if attributes.nil?
|
1058
|
-
|
1059
|
-
elsif
|
1060
|
-
|
1061
|
-
elsif
|
1062
|
-
|
1302
|
+
super
|
1303
|
+
elsif known_attributes.include?(method_name)
|
1304
|
+
true
|
1305
|
+
elsif method_name =~ /(?:=|\?)$/ && attributes.include?($`)
|
1306
|
+
true
|
1307
|
+
else
|
1308
|
+
# super must be called at the end of the method, because the inherited respond_to?
|
1309
|
+
# would return true for generated readers, even if the attribute wasn't present
|
1310
|
+
super
|
1063
1311
|
end
|
1064
|
-
# super must be called at the end of the method, because the inherited respond_to?
|
1065
|
-
# would return true for generated readers, even if the attribute wasn't present
|
1066
|
-
super
|
1067
1312
|
end
|
1068
1313
|
|
1069
|
-
|
1070
1314
|
protected
|
1071
1315
|
def connection(refresh = false)
|
1072
1316
|
self.class.connection(refresh)
|
@@ -1109,7 +1353,7 @@ module ActiveResource
|
|
1109
1353
|
private
|
1110
1354
|
# Tries to find a resource for a given collection name; if it fails, then the resource is created
|
1111
1355
|
def find_or_create_resource_for_collection(name)
|
1112
|
-
find_or_create_resource_for(name.to_s
|
1356
|
+
find_or_create_resource_for(ActiveSupport::Inflector.singularize(name.to_s))
|
1113
1357
|
end
|
1114
1358
|
|
1115
1359
|
# Tries to find a resource in a non empty list of nested modules
|
@@ -1153,14 +1397,24 @@ module ActiveResource
|
|
1153
1397
|
def method_missing(method_symbol, *arguments) #:nodoc:
|
1154
1398
|
method_name = method_symbol.to_s
|
1155
1399
|
|
1156
|
-
|
1400
|
+
if method_name =~ /(=|\?)$/
|
1401
|
+
case $1
|
1157
1402
|
when "="
|
1158
|
-
attributes[
|
1403
|
+
attributes[$`] = arguments.first
|
1159
1404
|
when "?"
|
1160
|
-
attributes[
|
1161
|
-
|
1162
|
-
|
1405
|
+
attributes[$`]
|
1406
|
+
end
|
1407
|
+
else
|
1408
|
+
return attributes[method_name] if attributes.include?(method_name)
|
1409
|
+
# not set right now but we know about it
|
1410
|
+
return nil if known_attributes.include?(method_name)
|
1411
|
+
super
|
1163
1412
|
end
|
1164
1413
|
end
|
1165
1414
|
end
|
1415
|
+
|
1416
|
+
class Base
|
1417
|
+
extend ActiveModel::Naming
|
1418
|
+
include CustomMethods, Observing, Validations
|
1419
|
+
end
|
1166
1420
|
end
|