activeresource 4.0.0 → 4.1.0
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.
- checksums.yaml +4 -4
- data/README.rdoc +16 -5
- data/lib/active_resource.rb +3 -0
- data/lib/active_resource/associations.rb +14 -10
- data/lib/active_resource/base.rb +88 -39
- data/lib/active_resource/collection.rb +2 -2
- data/lib/active_resource/connection.rb +27 -12
- data/lib/active_resource/http_mock.rb +44 -1
- data/lib/active_resource/railtie.rb +12 -1
- data/lib/active_resource/singleton.rb +1 -1
- data/lib/active_resource/threadsafe_attributes.rb +61 -0
- data/lib/active_resource/validations.rb +2 -2
- data/lib/active_resource/version.rb +1 -1
- data/lib/activeresource.rb +1 -0
- metadata +23 -21
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5ec4c5f35bfca437beeae8e7acb8763bc0ce1f96
|
4
|
+
data.tar.gz: 9ce68f2e6a206530f05c57ce23aaa0f240bc74f8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e8faca6d64850e4eb46e54d829c90355b7d18538b618032498e747dd27fc12861fac7e5e0d5ba53f4bf7eb7203f85c2dd092f0ad1a3badc3ed290a958558e820
|
7
|
+
data.tar.gz: 23fd61de41602794182b27df1703ae3e7a82dba3249c285524f6a5d681b792b9ea38ab782d1a4731b8ddf7a09eb3b78acf5ce0ea04cca8bf0f2d573129da1a9f
|
data/README.rdoc
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
= Active Resource
|
1
|
+
= Active Resource
|
2
2
|
|
3
3
|
Active Resource (ARes) connects business objects and Representational State Transfer (REST)
|
4
4
|
web services. It implements object-relational mapping for REST web services to provide transparent
|
@@ -28,7 +28,7 @@ The latest version of Active Resource can be installed with RubyGems:
|
|
28
28
|
|
29
29
|
Or added to a Gemfile:
|
30
30
|
|
31
|
-
gem 'activeresource'
|
31
|
+
gem 'activeresource'
|
32
32
|
|
33
33
|
Source code can be downloaded on GitHub
|
34
34
|
|
@@ -119,10 +119,12 @@ a 'Location' header in the response with the RESTful URL location of the newly c
|
|
119
119
|
id of the newly created resource is parsed out of the Location response header and automatically set
|
120
120
|
as the id of the ARes object.
|
121
121
|
|
122
|
-
# {"
|
122
|
+
# {"first":"Tyler","last":"Durden"}
|
123
123
|
#
|
124
124
|
# is submitted as the body on
|
125
125
|
#
|
126
|
+
# if include_root_in_json is set to true => {"person":{"first":"Tyler"}}
|
127
|
+
#
|
126
128
|
# POST http://api.people.com:3000/people.json
|
127
129
|
#
|
128
130
|
# when save is called on a new Person object. An empty response is
|
@@ -142,10 +144,12 @@ as the id of the ARes object.
|
|
142
144
|
with the exception that no response headers are needed -- just an empty response when the update on the
|
143
145
|
server side was successful.
|
144
146
|
|
145
|
-
# {"
|
147
|
+
# {"first":"Tyler"}
|
146
148
|
#
|
147
149
|
# is submitted as the body on
|
148
150
|
#
|
151
|
+
# if include_root_in_json is set to true => {"person":{"first":"Tyler"}}
|
152
|
+
#
|
149
153
|
# PUT http://api.people.com:3000/people/1.json
|
150
154
|
#
|
151
155
|
# when save is called on an existing Person object. An empty response is
|
@@ -207,11 +211,18 @@ Active Resource is released under the MIT license:
|
|
207
211
|
|
208
212
|
* http://www.opensource.org/licenses/MIT
|
209
213
|
|
214
|
+
== Contributing to Active Resource
|
215
|
+
|
216
|
+
Active Resource is work of many contributors. You're encouraged to submit pull requests, propose
|
217
|
+
features and discuss issues.
|
218
|
+
|
219
|
+
See {CONTRIBUTING}[https://github.com/rails/activeresource/blob/master/CONTRIBUTING.md].
|
220
|
+
|
210
221
|
== Support
|
211
222
|
|
212
223
|
API documentation is at
|
213
224
|
|
214
|
-
* http://
|
225
|
+
* http://rubydoc.info/gems/activeresource/4.0.0/frames
|
215
226
|
|
216
227
|
Bug reports and feature requests can be filed with the rest for the Ruby on Rails project here:
|
217
228
|
|
data/lib/active_resource.rb
CHANGED
@@ -14,7 +14,7 @@ module ActiveResource::Associations
|
|
14
14
|
# === Options
|
15
15
|
# [:class_name]
|
16
16
|
# Specify the class name of the association. This class name would
|
17
|
-
# be used for resolving the association class.
|
17
|
+
# be used for resolving the association class.
|
18
18
|
#
|
19
19
|
# ==== Example for [:class_name] - option
|
20
20
|
# GET /posts/123.json delivers following response body:
|
@@ -48,7 +48,7 @@ module ActiveResource::Associations
|
|
48
48
|
# === Options
|
49
49
|
# [:class_name]
|
50
50
|
# Specify the class name of the association. This class name would
|
51
|
-
# be used for resolving the association class.
|
51
|
+
# be used for resolving the association class.
|
52
52
|
#
|
53
53
|
# ==== Example for [:class_name] - option
|
54
54
|
# GET /posts/1.json delivers following response body:
|
@@ -67,14 +67,14 @@ module ActiveResource::Associations
|
|
67
67
|
# If the response body does not contain an attribute matching the association name
|
68
68
|
# a request is sent to a singelton path under the current resource.
|
69
69
|
# For example, if a Product class <tt>has_one :inventory</tt> calling <tt>Product#inventory</tt>
|
70
|
-
# will generate a request on /
|
70
|
+
# will generate a request on /products/:product_id/inventory.json.
|
71
71
|
#
|
72
72
|
def has_one(name, options = {})
|
73
73
|
Builder::HasOne.build(self, name, options)
|
74
74
|
end
|
75
75
|
|
76
76
|
# Specifies a one-to-one association with another class. This class should only be used
|
77
|
-
# if this class contains the foreign key.
|
77
|
+
# if this class contains the foreign key.
|
78
78
|
#
|
79
79
|
# Methods will be added for retrieval and query for a single associated object, for which
|
80
80
|
# this object holds an id:
|
@@ -83,7 +83,7 @@ module ActiveResource::Associations
|
|
83
83
|
# Returns the associated object. +nil+ is returned if the foreign key is +nil+.
|
84
84
|
# Throws a ActiveResource::ResourceNotFound exception if the foreign key is not +nil+
|
85
85
|
# and the resource is not found.
|
86
|
-
#
|
86
|
+
#
|
87
87
|
# (+association+ is replaced with the symbol passed as the first argument, so
|
88
88
|
# <tt>belongs_to :post</tt> would add among others <tt>post.nil?</tt>.
|
89
89
|
#
|
@@ -130,8 +130,8 @@ module ActiveResource::Associations
|
|
130
130
|
instance_variable_get(ivar_name)
|
131
131
|
elsif attributes.include?(method_name)
|
132
132
|
attributes[method_name]
|
133
|
-
|
134
|
-
instance_variable_set(ivar_name, association_model.find(
|
133
|
+
elsif association_id = send(finder_key)
|
134
|
+
instance_variable_set(ivar_name, association_model.find(association_id))
|
135
135
|
end
|
136
136
|
end
|
137
137
|
end
|
@@ -144,12 +144,14 @@ module ActiveResource::Associations
|
|
144
144
|
instance_variable_get(ivar_name)
|
145
145
|
elsif attributes.include?(method_name)
|
146
146
|
attributes[method_name]
|
147
|
-
|
147
|
+
elsif !new_record?
|
148
148
|
instance_variable_set(ivar_name, association_model.find(:all, :params => {:"#{self.class.element_name}_id" => self.id}))
|
149
|
+
else
|
150
|
+
instance_variable_set(ivar_name, self.class.collection_parser.new)
|
149
151
|
end
|
150
152
|
end
|
151
153
|
end
|
152
|
-
|
154
|
+
|
153
155
|
# Defines the has_one association
|
154
156
|
def defines_has_one_finder_method(method_name, association_model)
|
155
157
|
ivar_name = :"@#{method_name}"
|
@@ -159,8 +161,10 @@ module ActiveResource::Associations
|
|
159
161
|
instance_variable_get(ivar_name)
|
160
162
|
elsif attributes.include?(method_name)
|
161
163
|
attributes[method_name]
|
162
|
-
|
164
|
+
elsif association_model.respond_to?(:singleton_name)
|
163
165
|
instance_variable_set(ivar_name, association_model.find(:params => {:"#{self.class.element_name}_id" => self.id}))
|
166
|
+
else
|
167
|
+
instance_variable_set(ivar_name, association_model.find(:one, :from => "/#{self.class.collection_name}/#{self.id}/#{method_name}#{self.class.format_extension}"))
|
164
168
|
end
|
165
169
|
end
|
166
170
|
end
|
data/lib/active_resource/base.rb
CHANGED
@@ -18,6 +18,7 @@ require 'active_resource/schema'
|
|
18
18
|
require 'active_resource/log_subscriber'
|
19
19
|
require 'active_resource/associations'
|
20
20
|
require 'active_resource/reflection'
|
21
|
+
require 'active_resource/threadsafe_attributes'
|
21
22
|
|
22
23
|
module ActiveResource
|
23
24
|
# ActiveResource::Base is the main class for mapping RESTful resources as models in a Rails application.
|
@@ -283,6 +284,16 @@ module ActiveResource
|
|
283
284
|
# Internally, Active Resource relies on Ruby's Net::HTTP library to make HTTP requests. Setting +timeout+
|
284
285
|
# sets the <tt>read_timeout</tt> of the internal Net::HTTP instance to the same value. The default
|
285
286
|
# <tt>read_timeout</tt> is 60 seconds on most Ruby implementations.
|
287
|
+
#
|
288
|
+
# Active Resource also supports distinct +open_timeout+ (time to connect) and +read_timeout+ (how long to
|
289
|
+
# wait for an upstream response). This is inline with supported +Net::HTTP+ timeout configuration and allows
|
290
|
+
# for finer control of client timeouts depending on context.
|
291
|
+
#
|
292
|
+
# class Person < ActiveResource::Base
|
293
|
+
# self.site = "https://api.people.com"
|
294
|
+
# self.open_timeout = 2
|
295
|
+
# self.read_timeout = 10
|
296
|
+
# end
|
286
297
|
class Base
|
287
298
|
##
|
288
299
|
# :singleton-method:
|
@@ -294,7 +305,11 @@ module ActiveResource
|
|
294
305
|
class_attribute :include_format_in_path
|
295
306
|
self.include_format_in_path = true
|
296
307
|
|
308
|
+
|
297
309
|
class << self
|
310
|
+
include ThreadsafeAttributes
|
311
|
+
threadsafe_attribute :_headers, :_connection, :_user, :_password, :_site, :_proxy
|
312
|
+
|
298
313
|
# Creates a schema for this resource - setting the attributes that are
|
299
314
|
# known prior to fetching an instance from the remote system.
|
300
315
|
#
|
@@ -339,7 +354,7 @@ module ActiveResource
|
|
339
354
|
#
|
340
355
|
# p.num_children # => NoMethodError
|
341
356
|
#
|
342
|
-
# Attribute-types must be one of: <tt>string, integer, float</tt>
|
357
|
+
# Attribute-types must be one of: <tt>string, text, integer, float, decimal, datetime, timestamp, time, date, binary, boolean</tt>
|
343
358
|
#
|
344
359
|
# Note: at present the attribute-type doesn't do anything, but stay
|
345
360
|
# tuned...
|
@@ -431,8 +446,8 @@ module ActiveResource
|
|
431
446
|
# Subclass.site # => 'https://anonymous@test.com'
|
432
447
|
# Subclass.site.user = 'david' # => TypeError: can't modify frozen object
|
433
448
|
#
|
434
|
-
if
|
435
|
-
|
449
|
+
if _site_defined?
|
450
|
+
_site
|
436
451
|
elsif superclass != Object && superclass.site
|
437
452
|
superclass.site.dup.freeze
|
438
453
|
end
|
@@ -441,21 +456,21 @@ module ActiveResource
|
|
441
456
|
# Sets the URI of the REST resources to map for this class to the value in the +site+ argument.
|
442
457
|
# The site variable is required for Active Resource's mapping to work.
|
443
458
|
def site=(site)
|
444
|
-
|
459
|
+
self._connection = nil
|
445
460
|
if site.nil?
|
446
|
-
|
461
|
+
self._site = nil
|
447
462
|
else
|
448
|
-
|
449
|
-
|
450
|
-
|
463
|
+
self._site = create_site_uri_from(site)
|
464
|
+
self._user = URI.parser.unescape(_site.user) if _site.user
|
465
|
+
self._password = URI.parser.unescape(_site.password) if _site.password
|
451
466
|
end
|
452
467
|
end
|
453
468
|
|
454
469
|
# Gets the \proxy variable if a proxy is required
|
455
470
|
def proxy
|
456
471
|
# Not using superclass_delegating_reader. See +site+ for explanation
|
457
|
-
if
|
458
|
-
|
472
|
+
if _proxy_defined?
|
473
|
+
_proxy
|
459
474
|
elsif superclass != Object && superclass.proxy
|
460
475
|
superclass.proxy.dup.freeze
|
461
476
|
end
|
@@ -463,15 +478,15 @@ module ActiveResource
|
|
463
478
|
|
464
479
|
# Sets the URI of the http proxy to the value in the +proxy+ argument.
|
465
480
|
def proxy=(proxy)
|
466
|
-
|
467
|
-
|
481
|
+
self._connection = nil
|
482
|
+
self._proxy = proxy.nil? ? nil : create_proxy_uri_from(proxy)
|
468
483
|
end
|
469
484
|
|
470
485
|
# Gets the \user for REST HTTP authentication.
|
471
486
|
def user
|
472
487
|
# Not using superclass_delegating_reader. See +site+ for explanation
|
473
|
-
if
|
474
|
-
|
488
|
+
if _user_defined?
|
489
|
+
_user
|
475
490
|
elsif superclass != Object && superclass.user
|
476
491
|
superclass.user.dup.freeze
|
477
492
|
end
|
@@ -479,15 +494,15 @@ module ActiveResource
|
|
479
494
|
|
480
495
|
# Sets the \user for REST HTTP authentication.
|
481
496
|
def user=(user)
|
482
|
-
|
483
|
-
|
497
|
+
self._connection = nil
|
498
|
+
self._user = user
|
484
499
|
end
|
485
500
|
|
486
501
|
# Gets the \password for REST HTTP authentication.
|
487
502
|
def password
|
488
503
|
# Not using superclass_delegating_reader. See +site+ for explanation
|
489
|
-
if
|
490
|
-
|
504
|
+
if _password_defined?
|
505
|
+
_password
|
491
506
|
elsif superclass != Object && superclass.password
|
492
507
|
superclass.password.dup.freeze
|
493
508
|
end
|
@@ -495,8 +510,8 @@ module ActiveResource
|
|
495
510
|
|
496
511
|
# Sets the \password for REST HTTP authentication.
|
497
512
|
def password=(password)
|
498
|
-
|
499
|
-
|
513
|
+
self._connection = nil
|
514
|
+
self._password = password
|
500
515
|
end
|
501
516
|
|
502
517
|
def auth_type
|
@@ -506,7 +521,7 @@ module ActiveResource
|
|
506
521
|
end
|
507
522
|
|
508
523
|
def auth_type=(auth_type)
|
509
|
-
|
524
|
+
self._connection = nil
|
510
525
|
@auth_type = auth_type
|
511
526
|
end
|
512
527
|
|
@@ -544,10 +559,22 @@ module ActiveResource
|
|
544
559
|
|
545
560
|
# Sets the number of seconds after which requests to the REST API should time out.
|
546
561
|
def timeout=(timeout)
|
547
|
-
|
562
|
+
self._connection = nil
|
548
563
|
@timeout = timeout
|
549
564
|
end
|
550
565
|
|
566
|
+
# Sets the number of seconds after which connection attempts to the REST API should time out.
|
567
|
+
def open_timeout=(timeout)
|
568
|
+
self._connection = nil
|
569
|
+
@open_timeout = timeout
|
570
|
+
end
|
571
|
+
|
572
|
+
# Sets the number of seconds after which reads to the REST API should time out.
|
573
|
+
def read_timeout=(timeout)
|
574
|
+
self._connection = nil
|
575
|
+
@read_timeout = timeout
|
576
|
+
end
|
577
|
+
|
551
578
|
# Gets the number of seconds after which requests to the REST API should time out.
|
552
579
|
def timeout
|
553
580
|
if defined?(@timeout)
|
@@ -557,6 +584,24 @@ module ActiveResource
|
|
557
584
|
end
|
558
585
|
end
|
559
586
|
|
587
|
+
# Gets the number of seconds after which connection attempts to the REST API should time out.
|
588
|
+
def open_timeout
|
589
|
+
if defined?(@open_timeout)
|
590
|
+
@open_timeout
|
591
|
+
elsif superclass != Object && superclass.open_timeout
|
592
|
+
superclass.open_timeout
|
593
|
+
end
|
594
|
+
end
|
595
|
+
|
596
|
+
# Gets the number of seconds after which reads to the REST API should time out.
|
597
|
+
def read_timeout
|
598
|
+
if defined?(@read_timeout)
|
599
|
+
@read_timeout
|
600
|
+
elsif superclass != Object && superclass.read_timeout
|
601
|
+
superclass.read_timeout
|
602
|
+
end
|
603
|
+
end
|
604
|
+
|
560
605
|
# Options that will get applied to an SSL connection.
|
561
606
|
#
|
562
607
|
# * <tt>:key</tt> - An OpenSSL::PKey::RSA or OpenSSL::PKey::DSA object.
|
@@ -569,7 +614,7 @@ module ActiveResource
|
|
569
614
|
# * <tt>:cert_store</tt> - OpenSSL::X509::Store to verify peer certificate.
|
570
615
|
# * <tt>:ssl_timeout</tt> -The SSL timeout in seconds.
|
571
616
|
def ssl_options=(options)
|
572
|
-
|
617
|
+
self._connection = nil
|
573
618
|
@ssl_options = options
|
574
619
|
end
|
575
620
|
|
@@ -586,27 +631,28 @@ module ActiveResource
|
|
586
631
|
# The +refresh+ parameter toggles whether or not the \connection is refreshed at every request
|
587
632
|
# or not (defaults to <tt>false</tt>).
|
588
633
|
def connection(refresh = false)
|
589
|
-
if
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
634
|
+
if _connection_defined? || superclass == Object
|
635
|
+
self._connection = Connection.new(site, format) if refresh || _connection.nil?
|
636
|
+
_connection.proxy = proxy if proxy
|
637
|
+
_connection.user = user if user
|
638
|
+
_connection.password = password if password
|
639
|
+
_connection.auth_type = auth_type if auth_type
|
640
|
+
_connection.timeout = timeout if timeout
|
641
|
+
_connection.open_timeout = open_timeout if open_timeout
|
642
|
+
_connection.read_timeout = read_timeout if read_timeout
|
643
|
+
_connection.ssl_options = ssl_options if ssl_options
|
644
|
+
_connection
|
598
645
|
else
|
599
646
|
superclass.connection
|
600
647
|
end
|
601
648
|
end
|
602
649
|
|
603
650
|
def headers
|
604
|
-
|
605
|
-
|
651
|
+
self._headers ||= {}
|
606
652
|
if superclass != Object && superclass.headers
|
607
|
-
|
653
|
+
self._headers = superclass.headers.merge(_headers)
|
608
654
|
else
|
609
|
-
|
655
|
+
_headers
|
610
656
|
end
|
611
657
|
end
|
612
658
|
|
@@ -774,7 +820,7 @@ module ActiveResource
|
|
774
820
|
# Returns the new resource instance.
|
775
821
|
#
|
776
822
|
def build(attributes = {})
|
777
|
-
attrs = self.format.decode(connection.get("#{new_element_path(attributes)}", headers).body)
|
823
|
+
attrs = self.format.decode(connection.get("#{new_element_path(attributes)}", headers).body).merge(attributes)
|
778
824
|
self.new(attrs)
|
779
825
|
end
|
780
826
|
|
@@ -871,8 +917,8 @@ module ActiveResource
|
|
871
917
|
|
872
918
|
case scope
|
873
919
|
when :all then find_every(options)
|
874
|
-
when :first then find_every(options).first
|
875
|
-
when :last then find_every(options).last
|
920
|
+
when :first then find_every(options).to_a.first
|
921
|
+
when :last then find_every(options).to_a.last
|
876
922
|
when :one then find_one(options)
|
877
923
|
else find_single(scope, options)
|
878
924
|
end
|
@@ -1560,4 +1606,7 @@ module ActiveResource
|
|
1560
1606
|
include ActiveModel::Serializers::Xml
|
1561
1607
|
include ActiveResource::Reflection
|
1562
1608
|
end
|
1609
|
+
|
1610
|
+
ActiveSupport.run_load_hooks(:active_resource, Base)
|
1563
1611
|
end
|
1612
|
+
|
@@ -4,7 +4,7 @@ require 'active_support/inflector'
|
|
4
4
|
module ActiveResource # :nodoc:
|
5
5
|
class Collection # :nodoc:
|
6
6
|
include Enumerable
|
7
|
-
delegate :
|
7
|
+
delegate :to_yaml, :all?, *Array.instance_methods(false), :to => :to_a
|
8
8
|
|
9
9
|
# The array of actual elements returned by index actions
|
10
10
|
attr_accessor :elements, :resource_class, :original_params
|
@@ -31,7 +31,7 @@ module ActiveResource # :nodoc:
|
|
31
31
|
#
|
32
32
|
# class Post < ActiveResource::Base
|
33
33
|
# self.site = "http://example.com"
|
34
|
-
# self.collection_parser =
|
34
|
+
# self.collection_parser = PostCollection
|
35
35
|
# end
|
36
36
|
#
|
37
37
|
# And the collection parser:
|
@@ -20,7 +20,7 @@ module ActiveResource
|
|
20
20
|
:head => 'Accept'
|
21
21
|
}
|
22
22
|
|
23
|
-
attr_reader :site, :user, :password, :auth_type, :timeout, :proxy, :ssl_options
|
23
|
+
attr_reader :site, :user, :password, :auth_type, :timeout, :open_timeout, :read_timeout, :proxy, :ssl_options
|
24
24
|
attr_accessor :format
|
25
25
|
|
26
26
|
class << self
|
@@ -33,7 +33,7 @@ module ActiveResource
|
|
33
33
|
# attribute to the URI for the remote resource service.
|
34
34
|
def initialize(site, format = ActiveResource::Formats::JsonFormat)
|
35
35
|
raise ArgumentError, 'Missing site URI' unless site
|
36
|
-
@user = @password = nil
|
36
|
+
@proxy = @user = @password = nil
|
37
37
|
self.site = site
|
38
38
|
self.format = format
|
39
39
|
end
|
@@ -71,6 +71,16 @@ module ActiveResource
|
|
71
71
|
@timeout = timeout
|
72
72
|
end
|
73
73
|
|
74
|
+
# Sets the number of seconds after which HTTP connects to the remote service should time out.
|
75
|
+
def open_timeout=(timeout)
|
76
|
+
@open_timeout = timeout
|
77
|
+
end
|
78
|
+
|
79
|
+
# Sets the number of seconds after which HTTP read requests to the remote service should time out.
|
80
|
+
def read_timeout=(timeout)
|
81
|
+
@read_timeout = timeout
|
82
|
+
end
|
83
|
+
|
74
84
|
# Hash of options applied to Net::HTTP instance when +site+ protocol is 'https'.
|
75
85
|
def ssl_options=(options)
|
76
86
|
@ssl_options = options
|
@@ -180,6 +190,8 @@ module ActiveResource
|
|
180
190
|
https.open_timeout = @timeout
|
181
191
|
https.read_timeout = @timeout
|
182
192
|
end
|
193
|
+
https.open_timeout = @open_timeout if defined?(@open_timeout)
|
194
|
+
https.read_timeout = @read_timeout if defined?(@read_timeout)
|
183
195
|
end
|
184
196
|
end
|
185
197
|
|
@@ -260,16 +272,19 @@ module ActiveResource
|
|
260
272
|
end
|
261
273
|
|
262
274
|
def auth_attributes_for(uri, request_digest, params)
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
275
|
+
auth_attrs =
|
276
|
+
[
|
277
|
+
%Q(username="#{@user}"),
|
278
|
+
%Q(realm="#{params['realm']}"),
|
279
|
+
%Q(qop="#{params['qop']}"),
|
280
|
+
%Q(uri="#{uri.path}"),
|
281
|
+
%Q(nonce="#{params['nonce']}"),
|
282
|
+
%Q(nc="0"),
|
283
|
+
%Q(cnonce="#{params['cnonce']}"),
|
284
|
+
%Q(response="#{request_digest}")]
|
285
|
+
|
286
|
+
auth_attrs << %Q(opaque="#{params['opaque']}") unless params['opaque'].blank?
|
287
|
+
auth_attrs.join(", ")
|
273
288
|
end
|
274
289
|
|
275
290
|
def http_format_header(http_method)
|
@@ -214,6 +214,31 @@ module ActiveResource
|
|
214
214
|
requests.clear
|
215
215
|
responses.clear
|
216
216
|
end
|
217
|
+
|
218
|
+
# Enables all ActiveResource::Connection instances to use real
|
219
|
+
# Net::HTTP instance instead of a mock.
|
220
|
+
def enable_net_connection!
|
221
|
+
@@net_connection_enabled = true
|
222
|
+
end
|
223
|
+
|
224
|
+
# Sets all ActiveResource::Connection to use HttpMock instances.
|
225
|
+
def disable_net_connection!
|
226
|
+
@@net_connection_enabled = false
|
227
|
+
end
|
228
|
+
|
229
|
+
# Checks if real requests can be used instead of the default mock used in tests.
|
230
|
+
def net_connection_enabled?
|
231
|
+
if defined?(@@net_connection_enabled)
|
232
|
+
@@net_connection_enabled
|
233
|
+
else
|
234
|
+
@@net_connection_enabled = false
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
def net_connection_disabled?
|
239
|
+
!net_connection_enabled?
|
240
|
+
end
|
241
|
+
|
217
242
|
end
|
218
243
|
|
219
244
|
# body? methods
|
@@ -325,8 +350,26 @@ module ActiveResource
|
|
325
350
|
private
|
326
351
|
silence_warnings do
|
327
352
|
def http
|
328
|
-
|
353
|
+
if unstub_http?
|
354
|
+
@http = configure_http(new_http)
|
355
|
+
elsif stub_http?
|
356
|
+
@http = http_stub
|
357
|
+
end
|
358
|
+
@http ||= http_stub
|
329
359
|
end
|
360
|
+
|
361
|
+
def http_stub
|
362
|
+
HttpMock.new(@site)
|
363
|
+
end
|
364
|
+
|
365
|
+
def unstub_http?
|
366
|
+
HttpMock.net_connection_enabled? && defined?(@http) && @http.kind_of?(HttpMock)
|
367
|
+
end
|
368
|
+
|
369
|
+
def stub_http?
|
370
|
+
HttpMock.net_connection_disabled? && defined?(@http) && @http.kind_of?(Net::HTTP)
|
371
|
+
end
|
372
|
+
|
330
373
|
end
|
331
374
|
end
|
332
375
|
end
|
@@ -10,5 +10,16 @@ module ActiveResource
|
|
10
10
|
ActiveResource::Base.send "#{k}=", v
|
11
11
|
end
|
12
12
|
end
|
13
|
+
|
14
|
+
config.after_initialize do |app|
|
15
|
+
ActiveSupport.on_load(:active_resource) do
|
16
|
+
ActiveResource::Base.instantiate_observers
|
17
|
+
|
18
|
+
ActionDispatch::Reloader.to_prepare do
|
19
|
+
ActiveResource::Base.instantiate_observers
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
13
23
|
end
|
14
|
-
end
|
24
|
+
end
|
25
|
+
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module ThreadsafeAttributes
|
2
|
+
def self.included(klass)
|
3
|
+
klass.extend(ClassMethods)
|
4
|
+
end
|
5
|
+
|
6
|
+
module ClassMethods
|
7
|
+
def threadsafe_attribute(*attrs)
|
8
|
+
attrs.each do |attr|
|
9
|
+
define_method attr do
|
10
|
+
get_threadsafe_attribute(attr)
|
11
|
+
end
|
12
|
+
|
13
|
+
define_method "#{attr}=" do |value|
|
14
|
+
set_threadsafe_attribute(attr, value)
|
15
|
+
end
|
16
|
+
|
17
|
+
define_method "#{attr}_defined?" do
|
18
|
+
threadsafe_attribute_defined?(attr)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def get_threadsafe_attribute(name)
|
27
|
+
if threadsafe_attribute_defined_by_thread?(name, Thread.current)
|
28
|
+
get_threadsafe_attribute_by_thread(name, Thread.current)
|
29
|
+
elsif threadsafe_attribute_defined_by_thread?(name, Thread.main)
|
30
|
+
value = get_threadsafe_attribute_by_thread(name, Thread.main)
|
31
|
+
value = value.dup if value
|
32
|
+
set_threadsafe_attribute_by_thread(name, value, Thread.current)
|
33
|
+
value
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def set_threadsafe_attribute(name, value)
|
38
|
+
set_threadsafe_attribute_by_thread(name, value, Thread.current)
|
39
|
+
unless threadsafe_attribute_defined_by_thread?(name, Thread.main)
|
40
|
+
set_threadsafe_attribute_by_thread(name, value, Thread.main)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def threadsafe_attribute_defined?(name)
|
45
|
+
threadsafe_attribute_defined_by_thread?(name, Thread.current) || ((Thread.current != Thread.main) && threadsafe_attribute_defined_by_thread?(name, Thread.main))
|
46
|
+
end
|
47
|
+
|
48
|
+
def get_threadsafe_attribute_by_thread(name, thread)
|
49
|
+
thread["active.resource.#{name}.#{self.object_id}"]
|
50
|
+
end
|
51
|
+
|
52
|
+
def set_threadsafe_attribute_by_thread(name, value, thread)
|
53
|
+
thread["active.resource.#{name}.#{self.object_id}.defined"] = true
|
54
|
+
thread["active.resource.#{name}.#{self.object_id}"] = value
|
55
|
+
end
|
56
|
+
|
57
|
+
def threadsafe_attribute_defined_by_thread?(name, thread)
|
58
|
+
thread["active.resource.#{name}.#{self.object_id}.defined"]
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
@@ -13,7 +13,7 @@ module ActiveResource
|
|
13
13
|
# or not (by passing true).
|
14
14
|
def from_array(messages, save_cache = false)
|
15
15
|
clear unless save_cache
|
16
|
-
humanized_attributes = Hash[@base.
|
16
|
+
humanized_attributes = Hash[@base.known_attributes.map { |attr_name| [attr_name.humanize, attr_name] }]
|
17
17
|
messages.each do |message|
|
18
18
|
attr_message = humanized_attributes.keys.sort_by { |a| -a.length }.detect do |attr_name|
|
19
19
|
if message[0, attr_name.size + 1] == "#{attr_name} "
|
@@ -35,7 +35,7 @@ module ActiveResource
|
|
35
35
|
|
36
36
|
messages.each do |(key,errors)|
|
37
37
|
errors.each do |error|
|
38
|
-
if @base.
|
38
|
+
if @base.known_attributes.include?(key)
|
39
39
|
add key, error
|
40
40
|
elsif key == 'base'
|
41
41
|
self[:base] << error
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'active_resource'
|
metadata
CHANGED
@@ -1,83 +1,83 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activeresource
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.
|
4
|
+
version: 4.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Heinemeier Hansson
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-06-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - ~>
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '4.0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - ~>
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '4.0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: activemodel
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - ~>
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '4.0'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - ~>
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '4.0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rails-observers
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - ~>
|
45
|
+
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: 0.1.
|
47
|
+
version: 0.1.2
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - ~>
|
52
|
+
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: 0.1.
|
54
|
+
version: 0.1.2
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: rake
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- -
|
59
|
+
- - ">="
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '0'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- -
|
66
|
+
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: mocha
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- -
|
73
|
+
- - ">="
|
74
74
|
- !ruby/object:Gem::Version
|
75
75
|
version: 0.13.0
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- -
|
80
|
+
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: 0.13.0
|
83
83
|
description: REST on Rails. Wrap your RESTful web app with Ruby classes and work with
|
@@ -89,20 +89,21 @@ extra_rdoc_files:
|
|
89
89
|
- README.rdoc
|
90
90
|
files:
|
91
91
|
- README.rdoc
|
92
|
+
- lib/active_resource.rb
|
93
|
+
- lib/active_resource/associations.rb
|
92
94
|
- lib/active_resource/associations/builder/association.rb
|
93
95
|
- lib/active_resource/associations/builder/belongs_to.rb
|
94
96
|
- lib/active_resource/associations/builder/has_many.rb
|
95
97
|
- lib/active_resource/associations/builder/has_one.rb
|
96
|
-
- lib/active_resource/associations.rb
|
97
98
|
- lib/active_resource/base.rb
|
98
99
|
- lib/active_resource/callbacks.rb
|
99
100
|
- lib/active_resource/collection.rb
|
100
101
|
- lib/active_resource/connection.rb
|
101
102
|
- lib/active_resource/custom_methods.rb
|
102
103
|
- lib/active_resource/exceptions.rb
|
104
|
+
- lib/active_resource/formats.rb
|
103
105
|
- lib/active_resource/formats/json_format.rb
|
104
106
|
- lib/active_resource/formats/xml_format.rb
|
105
|
-
- lib/active_resource/formats.rb
|
106
107
|
- lib/active_resource/http_mock.rb
|
107
108
|
- lib/active_resource/log_subscriber.rb
|
108
109
|
- lib/active_resource/observing.rb
|
@@ -110,32 +111,33 @@ files:
|
|
110
111
|
- lib/active_resource/reflection.rb
|
111
112
|
- lib/active_resource/schema.rb
|
112
113
|
- lib/active_resource/singleton.rb
|
114
|
+
- lib/active_resource/threadsafe_attributes.rb
|
113
115
|
- lib/active_resource/validations.rb
|
114
116
|
- lib/active_resource/version.rb
|
115
|
-
- lib/
|
117
|
+
- lib/activeresource.rb
|
116
118
|
homepage: http://www.rubyonrails.org
|
117
119
|
licenses:
|
118
120
|
- MIT
|
119
121
|
metadata: {}
|
120
122
|
post_install_message:
|
121
123
|
rdoc_options:
|
122
|
-
- --main
|
124
|
+
- "--main"
|
123
125
|
- README.rdoc
|
124
126
|
require_paths:
|
125
127
|
- lib
|
126
128
|
required_ruby_version: !ruby/object:Gem::Requirement
|
127
129
|
requirements:
|
128
|
-
- -
|
130
|
+
- - ">="
|
129
131
|
- !ruby/object:Gem::Version
|
130
132
|
version: 1.9.3
|
131
133
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
132
134
|
requirements:
|
133
|
-
- -
|
135
|
+
- - ">="
|
134
136
|
- !ruby/object:Gem::Version
|
135
137
|
version: '0'
|
136
138
|
requirements: []
|
137
139
|
rubyforge_project:
|
138
|
-
rubygems_version: 2.
|
140
|
+
rubygems_version: 2.5.1
|
139
141
|
signing_key:
|
140
142
|
specification_version: 4
|
141
143
|
summary: REST modeling framework (part of Rails).
|