activeresource 5.0.0 → 5.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: f09e2bfd3d8332924184d674556d18d2d0533dcf
4
- data.tar.gz: 5dbc9edf5003415fd3565692dffa8a6342d0a1b2
2
+ SHA256:
3
+ metadata.gz: 5ba8858054bdc522433ffd05850eb3246ef21e3aee7ffab4aec2590ebe8eedfd
4
+ data.tar.gz: e52b3454a54fb9c6a97176da0464556ae645a3f7e0a8370fb0342dc3e9795eb1
5
5
  SHA512:
6
- metadata.gz: 27ba6aabd0eea02c3f2adb1d6d92311c94415d9ac32589f24abc517f1384a0ab6471717ab50e017a4993b069452f85e636053e3e49ffeb37c60873fcc4f9f671
7
- data.tar.gz: 3c8c8780b50ada3328e3df5b0d544e19cc3977dd4199c750991f403e00cfaa9c45213328cfdc717ebb0d86bbd931bc8b48724f17d7c56d7f996c6ace763e0ad6
6
+ metadata.gz: f716f552fb861f8aadc6ddcaf5265076d905d0428b3fdb368b52a21030b1ba33acd148c8dd548801f5f7fe2cf13a3c94055079ae22a378d9ad26b56cb244df3a
7
+ data.tar.gz: d7103ae2decdd750363b186ef5895eb18a04f4450b9815f98b74d0391445acaa3eae1084a53f0bff1774be7dca88cadd19bde4849f864a093bb6213d06879da9
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2006-2016 David Heinemeier Hansson
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -30,10 +30,6 @@ Or added to a Gemfile:
30
30
 
31
31
  gem 'activeresource'
32
32
 
33
- For compatibility with Rails 5, use:
34
-
35
- gem 'activeresource', github: 'rails/activeresource', branch: 'master'
36
-
37
33
  Source code can be downloaded on GitHub
38
34
 
39
35
  * https://github.com/rails/activeresource/tree/master/activeresource
@@ -57,6 +53,11 @@ life cycle methods that operate against a persistent store.
57
53
  As you can see, the methods are quite similar to Active Record's methods for dealing with database
58
54
  records. But rather than dealing directly with a database record, you're dealing with HTTP resources (which may or may not be database records).
59
55
 
56
+ Connection settings (`site`, `headers`, `user`, `password`, `proxy`) and the connections themselves are store in
57
+ thread-local variables to make them thread-safe, so you can also set these dynamically, even in a multi-threaded environment, for instance:
58
+
59
+ ActiveResource::Base.site = api_site_for(request)
60
+
60
61
  ==== Authentication
61
62
 
62
63
  Active Resource supports the token based authentication provided by Rails through the <tt>ActionController::HttpAuthentication::Token</tt> class using custom headers.
@@ -64,8 +65,32 @@ Active Resource supports the token based authentication provided by Rails throug
64
65
  class Person < ActiveResource::Base
65
66
  self.headers['Authorization'] = 'Token token="abcd"'
66
67
  end
67
-
68
- You can also set any specific HTTP header using the same way.
68
+
69
+ You can also set any specific HTTP header using the same way. As mentioned above, headers are thread-safe, so you can set headers dynamically, even in a multi-threaded environment:
70
+
71
+ ActiveResource::Base.headers['Authorization'] = current_session_api_token
72
+
73
+ Global Authentication to be used across all subclasses of ActiveResource::Base should be handled using the ActiveResource::Connection class.
74
+
75
+ ActiveResource::Base.connection.auth_type = :bearer
76
+ ActiveResource::Base.connection.bearer_token = @bearer_token
77
+
78
+ class Person < ActiveResource::Base
79
+ self.connection.auth_type = :bearer
80
+ self.connection.bearer_token = @bearer_token
81
+ end
82
+
83
+ ActiveResource supports 2 options for HTTP authentication today.
84
+
85
+ 1. Basic
86
+
87
+ ActiveResource::Connection.new("http://my%40email.com:%31%32%33@localhost")
88
+ # username: my@email.com password: 123
89
+
90
+ 2. Bearer Token
91
+
92
+ ActiveResource::Base.connection.auth_type = :bearer
93
+ ActiveResource::Base.connection.bearer_token = @bearer_token
69
94
 
70
95
  ==== Protocol
71
96
 
@@ -115,7 +140,7 @@ Collections can also be requested in a similar fashion
115
140
 
116
141
  # Expects a response of
117
142
  #
118
- # [
143
+ # [
119
144
  # {"id":1,"first":"Tyler","last":"Durden"},
120
145
  # {"id":2,"first":"Tony","last":"Stark",}
121
146
  # ]
@@ -205,7 +230,7 @@ class definition below:
205
230
  end
206
231
 
207
232
  post = Post.find(1) # issues GET http://blog.io/posts/1.json
208
- comments = post.comments # issues GET http://blog.io/posts/1/comments.json
233
+ comments = post.comments # issues GET http://blog.io/comments.json?post_id=1
209
234
 
210
235
 
211
236
  If you control the server, you may wish to include nested resources thus avoiding a
@@ -221,6 +246,19 @@ The server-side model can be adjusted as follows to include comments in the resp
221
246
  end
222
247
  end
223
248
 
249
+ ==== Logging
250
+
251
+ Active Resource instruments the event `request.active_resource` when doing a request
252
+ to the remote service. You can subscribe to it by doing:
253
+
254
+ ActiveSupport::Notifications.subscribe('request.active_resource') do |name, start, finish, id, payload|
255
+
256
+ The `payload` is a `Hash` with the following keys:
257
+
258
+ * `method` as a `Symbol`
259
+ * `request_uri` as a `String`
260
+ * `result` as an `Net::HTTPResponse`
261
+
224
262
  == License
225
263
 
226
264
  Active Resource is released under the MIT license:
@@ -236,9 +274,9 @@ See {CONTRIBUTING}[https://github.com/rails/activeresource/blob/master/CONTRIBUT
236
274
 
237
275
  == Support
238
276
 
239
- API documentation is at
277
+ Full API documentation is available at
240
278
 
241
- * http://rubydoc.info/gems/activeresource/4.0.0/frames
279
+ * http://rubydoc.info/gems/activeresource
242
280
 
243
281
  Bug reports and feature requests can be filed with the rest for the Ruby on Rails project here:
244
282
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  #--
2
4
  # Copyright (c) 2006-2012 David Heinemeier Hansson
3
5
  #
@@ -21,10 +23,10 @@
21
23
  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
24
  #++
23
25
 
24
- require 'active_support'
25
- require 'active_model'
26
- require 'active_resource/exceptions'
27
- require 'active_resource/version'
26
+ require "active_support"
27
+ require "active_model"
28
+ require "active_resource/exceptions"
29
+ require "active_resource/version"
28
30
 
29
31
  module ActiveResource
30
32
  extend ActiveSupport::Autoload
@@ -41,4 +43,4 @@ module ActiveResource
41
43
  autoload :Collection
42
44
  end
43
45
 
44
- require 'active_resource/railtie' if defined?(Rails.application)
46
+ require "active_resource/railtie" if defined?(Rails.application)
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveResource
4
+ class ActiveJobSerializer < ActiveJob::Serializers::ObjectSerializer
5
+ def serialize(resource)
6
+ super(
7
+ "class" => resource.class.name,
8
+ "persisted" => resource.persisted?,
9
+ "prefix_options" => resource.prefix_options.as_json,
10
+ "attributes" => resource.attributes.as_json
11
+ )
12
+ end
13
+
14
+ def deserialize(hash)
15
+ hash["class"].constantize.new(hash["attributes"]).tap do |resource|
16
+ resource.persisted = hash["persisted"]
17
+ resource.prefix_options = hash["prefix_options"]
18
+ end
19
+ end
20
+
21
+ private
22
+ def klass
23
+ ActiveResource::Base
24
+ end
25
+ end
26
+ end
@@ -1,10 +1,11 @@
1
- module ActiveResource::Associations
1
+ # frozen_string_literal: true
2
2
 
3
+ module ActiveResource::Associations
3
4
  module Builder
4
- autoload :Association, 'active_resource/associations/builder/association'
5
- autoload :HasMany, 'active_resource/associations/builder/has_many'
6
- autoload :HasOne, 'active_resource/associations/builder/has_one'
7
- autoload :BelongsTo, 'active_resource/associations/builder/belongs_to'
5
+ autoload :Association, "active_resource/associations/builder/association"
6
+ autoload :HasMany, "active_resource/associations/builder/has_many"
7
+ autoload :HasOne, "active_resource/associations/builder/has_one"
8
+ autoload :BelongsTo, "active_resource/associations/builder/belongs_to"
8
9
  end
9
10
 
10
11
 
@@ -112,7 +113,7 @@ module ActiveResource::Associations
112
113
  # <tt>belongs_to :customer, :foreign_key => 'user_id'</tt>
113
114
  # Creates a belongs_to association called customer which would be resolved by the foreign_key <tt>user_id</tt> instead of <tt>customer_id</tt>
114
115
  #
115
- def belongs_to(name, options={})
116
+ def belongs_to(name, options = {})
116
117
  Builder::BelongsTo.build(self, name, options)
117
118
  end
118
119
 
@@ -147,7 +148,7 @@ module ActiveResource::Associations
147
148
  elsif attributes.include?(method_name)
148
149
  attributes[method_name]
149
150
  elsif !new_record?
150
- instance_variable_set(ivar_name, reflection.klass.find(:all, :params => {:"#{self.class.element_name}_id" => self.id}))
151
+ instance_variable_set(ivar_name, reflection.klass.find(:all, params: { :"#{self.class.element_name}_id" => self.id }))
151
152
  else
152
153
  instance_variable_set(ivar_name, self.class.collection_parser.new)
153
154
  end
@@ -165,11 +166,10 @@ module ActiveResource::Associations
165
166
  elsif attributes.include?(method_name)
166
167
  attributes[method_name]
167
168
  elsif reflection.klass.respond_to?(:singleton_name)
168
- instance_variable_set(ivar_name, reflection.klass.find(:params => {:"#{self.class.element_name}_id" => self.id}))
169
+ instance_variable_set(ivar_name, reflection.klass.find(params: { :"#{self.class.element_name}_id" => self.id }))
169
170
  else
170
- instance_variable_set(ivar_name, reflection.klass.find(:one, :from => "/#{self.class.collection_name}/#{self.id}/#{method_name}#{self.class.format_extension}"))
171
+ instance_variable_set(ivar_name, reflection.klass.find(:one, from: "/#{self.class.collection_name}/#{self.id}/#{method_name}#{self.class.format_extension}"))
171
172
  end
172
173
  end
173
174
  end
174
-
175
175
  end
@@ -1,6 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveResource::Associations::Builder
2
4
  class Association #:nodoc:
3
-
4
5
  # providing a Class-Variable, which will have a different store of subclasses
5
6
  class_attribute :valid_options
6
7
  self.valid_options = [:class_name]
@@ -25,8 +26,8 @@ module ActiveResource::Associations::Builder
25
26
 
26
27
  private
27
28
 
28
- def validate_options
29
- options.assert_valid_keys(self.class.valid_options)
30
- end
29
+ def validate_options
30
+ options.assert_valid_keys(self.class.valid_options)
31
+ end
31
32
  end
32
33
  end
@@ -1,4 +1,6 @@
1
- module ActiveResource::Associations::Builder
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveResource::Associations::Builder
2
4
  class BelongsTo < Association
3
5
  self.valid_options += [:foreign_key]
4
6
 
@@ -8,7 +10,7 @@ module ActiveResource::Associations::Builder
8
10
  validate_options
9
11
  reflection = model.create_reflection(self.class.macro, name, options)
10
12
  model.defines_belongs_to_finder_method(reflection)
11
- return reflection
13
+ reflection
12
14
  end
13
15
  end
14
16
  end
@@ -1,4 +1,6 @@
1
- module ActiveResource::Associations::Builder
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveResource::Associations::Builder
2
4
  class HasMany < Association
3
5
  self.macro = :has_many
4
6
 
@@ -1,7 +1,9 @@
1
- module ActiveResource::Associations::Builder
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveResource::Associations::Builder
2
4
  class HasOne < Association
3
5
  self.macro = :has_one
4
-
6
+
5
7
  def build
6
8
  validate_options
7
9
  model.create_reflection(self.class.macro, name, options).tap do |reflection|
@@ -1,26 +1,28 @@
1
- require 'active_support'
2
- require 'active_support/core_ext/class/attribute_accessors'
3
- require 'active_support/core_ext/class/attribute'
4
- require 'active_support/core_ext/hash/indifferent_access'
5
- require 'active_support/core_ext/kernel/reporting'
6
- require 'active_support/core_ext/module/delegation'
7
- require 'active_support/core_ext/module/aliasing'
8
- require 'active_support/core_ext/object/blank'
9
- require 'active_support/core_ext/object/to_query'
10
- require 'active_support/core_ext/object/duplicable'
11
- require 'set'
12
- require 'uri'
13
-
14
- require 'active_support/core_ext/uri'
15
- require 'active_resource/connection'
16
- require 'active_resource/formats'
17
- require 'active_resource/schema'
18
- require 'active_resource/log_subscriber'
19
- require 'active_resource/associations'
20
- require 'active_resource/reflection'
21
- require 'active_resource/threadsafe_attributes'
22
-
23
- require 'active_model/serializers/xml'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support"
4
+ require "active_support/core_ext/class/attribute_accessors"
5
+ require "active_support/core_ext/class/attribute"
6
+ require "active_support/core_ext/hash/indifferent_access"
7
+ require "active_support/core_ext/kernel/reporting"
8
+ require "active_support/core_ext/module/delegation"
9
+ require "active_support/core_ext/module/aliasing"
10
+ require "active_support/core_ext/object/blank"
11
+ require "active_support/core_ext/object/to_query"
12
+ require "active_support/core_ext/object/duplicable"
13
+ require "set"
14
+ require "uri"
15
+
16
+ require "active_support/core_ext/uri"
17
+ require "active_resource/connection"
18
+ require "active_resource/formats"
19
+ require "active_resource/schema"
20
+ require "active_resource/log_subscriber"
21
+ require "active_resource/associations"
22
+ require "active_resource/reflection"
23
+ require "active_resource/threadsafe_attributes"
24
+
25
+ require "active_model/serializers/xml"
24
26
 
25
27
  module ActiveResource
26
28
  # ActiveResource::Base is the main class for mapping RESTful resources as models in a Rails application.
@@ -300,7 +302,12 @@ module ActiveResource
300
302
  ##
301
303
  # :singleton-method:
302
304
  # The logger for diagnosing and tracing Active Resource calls.
303
- cattr_accessor :logger
305
+ cattr_reader :logger
306
+
307
+ def self.logger=(logger)
308
+ self._connection = nil
309
+ @@logger = logger
310
+ end
304
311
 
305
312
  class_attribute :_format
306
313
  class_attribute :_collection_parser
@@ -378,7 +385,7 @@ module ActiveResource
378
385
  @schema ||= {}.with_indifferent_access
379
386
  @known_attributes ||= []
380
387
 
381
- schema_definition.attrs.each do |k,v|
388
+ schema_definition.attrs.each do |k, v|
382
389
  @schema[k] = v
383
390
  @known_attributes << k
384
391
  end
@@ -417,7 +424,7 @@ module ActiveResource
417
424
  raise ArgumentError, "Expected a hash" unless the_schema.kind_of? Hash
418
425
 
419
426
  schema do
420
- the_schema.each {|k,v| attribute(k,v) }
427
+ the_schema.each { |k, v| attribute(k, v) }
421
428
  end
422
429
  end
423
430
 
@@ -619,7 +626,7 @@ module ActiveResource
619
626
  # * <tt>:ssl_timeout</tt> -The SSL timeout in seconds.
620
627
  def ssl_options=(options)
621
628
  self._connection = nil
622
- @ssl_options = options
629
+ @ssl_options = options
623
630
  end
624
631
 
625
632
  # Returns the SSL options hash.
@@ -636,7 +643,9 @@ module ActiveResource
636
643
  # or not (defaults to <tt>false</tt>).
637
644
  def connection(refresh = false)
638
645
  if _connection_defined? || superclass == Object
639
- self._connection = connection_class.new(site, format) if refresh || _connection.nil?
646
+ self._connection = connection_class.new(
647
+ site, format, logger: logger
648
+ ) if refresh || _connection.nil?
640
649
  _connection.proxy = proxy if proxy
641
650
  _connection.user = user if user
642
651
  _connection.password = password if password
@@ -682,15 +691,15 @@ module ActiveResource
682
691
  return primary_key if primary_key.is_a?(Symbol)
683
692
  primary_key.dup.freeze
684
693
  else
685
- 'id'
694
+ "id"
686
695
  end
687
696
  end
688
697
 
689
698
  # Gets the \prefix for a resource's nested URL (e.g., <tt>prefix/collectionname/1.json</tt>)
690
699
  # This method is regenerated at runtime based on what the \prefix is set to.
691
- def prefix(options={})
700
+ def prefix(options = {})
692
701
  default = site.path
693
- default << '/' unless default[-1..-1] == '/'
702
+ default << "/" unless default[-1..-1] == "/"
694
703
  # generate the actual method based on the current site path
695
704
  self.prefix = default
696
705
  prefix(options)
@@ -705,7 +714,7 @@ module ActiveResource
705
714
 
706
715
  # Sets the \prefix for a resource's nested URL (e.g., <tt>prefix/collectionname/1.json</tt>).
707
716
  # Default value is <tt>site.path</tt>.
708
- def prefix=(value = '/')
717
+ def prefix=(value = "/")
709
718
  # Replace :placeholders with '#{embedded options[:lookups]}'
710
719
  prefix_call = value.gsub(/:\w+/) { |key| "\#{URI.parser.escape options[#{key}].to_s}" }
711
720
 
@@ -766,6 +775,36 @@ module ActiveResource
766
775
  "#{prefix(prefix_options)}#{collection_name}/#{URI.parser.escape id.to_s}#{format_extension}#{query_string(query_options)}"
767
776
  end
768
777
 
778
+ # Gets the element url for the given ID in +id+. If the +query_options+ parameter is omitted, Rails
779
+ # will split from the \prefix options.
780
+ #
781
+ # ==== Options
782
+ # +prefix_options+ - A \hash to add a \prefix to the request for nested URLs (e.g., <tt>:account_id => 19</tt>
783
+ # would yield a URL like <tt>https://37s.sunrise.com/accounts/19/purchases.json</tt>).
784
+ #
785
+ # +query_options+ - A \hash to add items to the query string for the request.
786
+ #
787
+ # ==== Examples
788
+ # Post.element_url(1)
789
+ # # => https://37s.sunrise.com/posts/1.json
790
+ #
791
+ # class Comment < ActiveResource::Base
792
+ # self.site = "https://37s.sunrise.com/posts/:post_id"
793
+ # end
794
+ #
795
+ # Comment.element_url(1, :post_id => 5)
796
+ # # => https://37s.sunrise.com/posts/5/comments/1.json
797
+ #
798
+ # Comment.element_url(1, :post_id => 5, :active => 1)
799
+ # # => https://37s.sunrise.com/posts/5/comments/1.json?active=1
800
+ #
801
+ # Comment.element_url(1, {:post_id => 5}, {:active => 1})
802
+ # # => https://37s.sunrise.com/posts/5/comments/1.json?active=1
803
+ #
804
+ def element_url(id, prefix_options = {}, query_options = nil)
805
+ URI.join(site, element_path(id, prefix_options, query_options)).to_s
806
+ end
807
+
769
808
  # Gets the new element path for REST resources.
770
809
  #
771
810
  # ==== Options
@@ -931,11 +970,18 @@ module ActiveResource
931
970
  options = arguments.slice!(0) || {}
932
971
 
933
972
  case scope
934
- when :all then find_every(options)
935
- when :first then find_every(options).to_a.first
936
- when :last then find_every(options).to_a.last
937
- when :one then find_one(options)
938
- else find_single(scope, options)
973
+ when :all
974
+ find_every(options)
975
+ when :first
976
+ collection = find_every(options)
977
+ collection && collection.first
978
+ when :last
979
+ collection = find_every(options)
980
+ collection && collection.last
981
+ when :one
982
+ find_one(options)
983
+ else
984
+ find_single(scope, options)
939
985
  end
940
986
  end
941
987
 
@@ -962,7 +1008,7 @@ module ActiveResource
962
1008
 
963
1009
  def where(clauses = {})
964
1010
  raise ArgumentError, "expected a clauses Hash, got #{clauses.inspect}" unless clauses.is_a? Hash
965
- find(:all, :params => clauses)
1011
+ find(:all, params: clauses)
966
1012
  end
967
1013
 
968
1014
 
@@ -996,7 +1042,7 @@ module ActiveResource
996
1042
  prefix_options, query_options = split_options(options[:params])
997
1043
  path = element_path(id, prefix_options, query_options)
998
1044
  response = connection.head(path, headers)
999
- (200..206).include? response.code
1045
+ (200..206).include? response.code.to_i
1000
1046
  end
1001
1047
  # id && !find_single(id, options).nil?
1002
1048
  rescue ActiveResource::ResourceNotFound, ActiveResource::ResourceGone
@@ -1024,7 +1070,7 @@ module ActiveResource
1024
1070
  else
1025
1071
  prefix_options, query_options = split_options(options[:params])
1026
1072
  path = collection_path(prefix_options, query_options)
1027
- instantiate_collection( (format.decode(connection.get(path, headers).body) || []), query_options, prefix_options )
1073
+ instantiate_collection((format.decode(connection.get(path, headers).body) || []), query_options, prefix_options)
1028
1074
  end
1029
1075
  rescue ActiveResource::ResourceNotFound
1030
1076
  # Swallowing ResourceNotFound exceptions and return nil - as per
@@ -1091,8 +1137,8 @@ module ActiveResource
1091
1137
  prefix_options, query_options = {}, {}
1092
1138
 
1093
1139
  (options || {}).each do |key, value|
1094
- next if key.blank? || !key.respond_to?(:to_sym)
1095
- (prefix_parameters.include?(key.to_sym) ? prefix_options : query_options)[key.to_sym] = value
1140
+ next if key.blank?
1141
+ (prefix_parameters.include?(key.to_s.to_sym) ? prefix_options : query_options)[key.to_s.to_sym] = value
1096
1142
  end
1097
1143
 
1098
1144
  [ prefix_options, query_options ]
@@ -1157,13 +1203,13 @@ module ActiveResource
1157
1203
  # not_ryan.hash # => {:not => "an ARes instance"}
1158
1204
  def clone
1159
1205
  # Clone all attributes except the pk and any nested ARes
1160
- cloned = Hash[attributes.reject {|k,v| k == self.class.primary_key || v.is_a?(ActiveResource::Base)}.map { |k, v| [k, v.clone] }]
1206
+ cloned = Hash[attributes.reject { |k, v| k == self.class.primary_key || v.is_a?(ActiveResource::Base) }.map { |k, v| [k, v.clone] }]
1161
1207
  # Form the new resource - bypass initialize of resource with 'new' as that will call 'load' which
1162
1208
  # attempts to convert hashes into member objects and arrays into collections of objects. We want
1163
1209
  # the raw objects to be cloned so we bypass load by directly setting the attributes hash.
1164
1210
  resource = self.class.new({})
1165
1211
  resource.prefix_options = self.prefix_options
1166
- resource.send :instance_variable_set, '@attributes', cloned
1212
+ resource.send :instance_variable_set, "@attributes", cloned
1167
1213
  resource
1168
1214
  end
1169
1215
 
@@ -1338,13 +1384,13 @@ module ActiveResource
1338
1384
  # Person.delete(guys_id)
1339
1385
  # that_guy.exists? # => false
1340
1386
  def exists?
1341
- !new? && self.class.exists?(to_param, :params => prefix_options)
1387
+ !new? && self.class.exists?(to_param, params: prefix_options)
1342
1388
  end
1343
1389
 
1344
1390
  # Returns the serialized string representation of the resource in the configured
1345
1391
  # serialization format specified in ActiveResource::Base.format. The options
1346
1392
  # applicable depend on the configured encoding format.
1347
- def encode(options={})
1393
+ def encode(options = {})
1348
1394
  send("to_#{self.class.format.extension}", options)
1349
1395
  end
1350
1396
 
@@ -1360,7 +1406,7 @@ module ActiveResource
1360
1406
  # my_branch.reload
1361
1407
  # my_branch.name # => "Wilson Road"
1362
1408
  def reload
1363
- self.load(self.class.find(to_param, :params => @prefix_options).attributes, false, true)
1409
+ self.load(self.class.find(to_param, params: @prefix_options).attributes, false, true)
1364
1410
  end
1365
1411
 
1366
1412
  # A method to manually load attributes from a \hash. Recursively loads collections of
@@ -1401,21 +1447,21 @@ module ActiveResource
1401
1447
  attributes.each do |key, value|
1402
1448
  @attributes[key.to_s] =
1403
1449
  case value
1404
- when Array
1405
- resource = nil
1406
- value.map do |attrs|
1407
- if attrs.is_a?(Hash)
1408
- resource ||= find_or_create_resource_for_collection(key)
1409
- resource.new(attrs, persisted)
1410
- else
1411
- attrs.duplicable? ? attrs.dup : attrs
1412
- end
1450
+ when Array
1451
+ resource = nil
1452
+ value.map do |attrs|
1453
+ if attrs.is_a?(Hash)
1454
+ resource ||= find_or_create_resource_for_collection(key)
1455
+ resource.new(attrs, persisted)
1456
+ else
1457
+ attrs.duplicable? ? attrs.dup : attrs
1413
1458
  end
1414
- when Hash
1415
- resource = find_or_create_resource_for(key)
1416
- resource.new(value, persisted)
1417
- else
1418
- value.duplicable? ? value.dup : value
1459
+ end
1460
+ when Hash
1461
+ resource = find_or_create_resource_for(key)
1462
+ resource.new(value, persisted)
1463
+ else
1464
+ value.duplicable? ? value.dup : value
1419
1465
  end
1420
1466
  end
1421
1467
  self
@@ -1472,12 +1518,20 @@ module ActiveResource
1472
1518
  end
1473
1519
  end
1474
1520
 
1475
- def to_json(options={})
1476
- super(include_root_in_json ? { :root => self.class.element_name }.merge(options) : options)
1521
+ def to_json(options = {})
1522
+ super(include_root_in_json ? { root: self.class.element_name }.merge(options) : options)
1477
1523
  end
1478
1524
 
1479
- def to_xml(options={})
1480
- super({ :root => self.class.element_name }.merge(options))
1525
+ def to_xml(options = {})
1526
+ super({ root: self.class.element_name }.merge(options))
1527
+ end
1528
+
1529
+ def read_attribute_for_serialization(n)
1530
+ if !attributes[n].nil?
1531
+ attributes[n]
1532
+ elsif respond_to?(n)
1533
+ send(n)
1534
+ end
1481
1535
  end
1482
1536
 
1483
1537
  protected
@@ -1505,9 +1559,9 @@ module ActiveResource
1505
1559
  end
1506
1560
 
1507
1561
  def load_attributes_from_response(response)
1508
- if (response_code_allows_body?(response.code) &&
1509
- (response['Content-Length'].nil? || response['Content-Length'] != "0") &&
1510
- !response.body.nil? && response.body.strip.size > 0)
1562
+ if response_code_allows_body?(response.code.to_i) &&
1563
+ (response["Content-Length"].nil? || response["Content-Length"] != "0") &&
1564
+ !response.body.nil? && response.body.strip.size > 0
1511
1565
  load(self.class.format.decode(response.body), true, true)
1512
1566
  @persisted = true
1513
1567
  end
@@ -1515,13 +1569,17 @@ module ActiveResource
1515
1569
 
1516
1570
  # Takes a response from a typical create post and pulls the ID out
1517
1571
  def id_from_response(response)
1518
- response['Location'][/\/([^\/]*?)(\.\w+)?$/, 1] if response['Location']
1572
+ response["Location"][/\/([^\/]*?)(\.\w+)?$/, 1] if response["Location"]
1519
1573
  end
1520
1574
 
1521
1575
  def element_path(options = nil)
1522
1576
  self.class.element_path(to_param, options || prefix_options)
1523
1577
  end
1524
1578
 
1579
+ def element_url(options = nil)
1580
+ self.class.element_url(to_param, options || prefix_options)
1581
+ end
1582
+
1525
1583
  def new_element_path
1526
1584
  self.class.new_element_path(prefix_options)
1527
1585
  end
@@ -1532,13 +1590,9 @@ module ActiveResource
1532
1590
 
1533
1591
  private
1534
1592
 
1535
- def read_attribute_for_serialization(n)
1536
- attributes[n]
1537
- end
1538
-
1539
1593
  # Determine whether the response is allowed to have a body per HTTP 1.1 spec section 4.4.1
1540
1594
  def response_code_allows_body?(c)
1541
- !((100..199).include?(c) || [204,304].include?(c))
1595
+ !((100..199).include?(c) || [204, 304].include?(c))
1542
1596
  end
1543
1597
 
1544
1598
  # Tries to find a resource for a given collection name; if it fails, then the resource is created
@@ -1551,7 +1605,7 @@ module ActiveResource
1551
1605
  # if it fails, then the resource is created
1552
1606
  def find_or_create_resource_in_modules(resource_name, module_names)
1553
1607
  receiver = Object
1554
- namespaces = module_names[0, module_names.size-1].map do |module_name|
1608
+ namespaces = module_names[0, module_names.size - 1].map do |module_name|
1555
1609
  receiver = receiver.const_get(module_name)
1556
1610
  end
1557
1611
  const_args = [resource_name, false]
@@ -1568,7 +1622,11 @@ module ActiveResource
1568
1622
  resource_name = name.to_s.camelize
1569
1623
 
1570
1624
  const_args = [resource_name, false]
1571
- if self.class.const_defined?(*const_args)
1625
+
1626
+ if !const_valid?(*const_args)
1627
+ # resource_name is not a valid ruby module name and cannot be created normally
1628
+ find_or_create_resource_for(:UnnamedResource)
1629
+ elsif self.class.const_defined?(*const_args)
1572
1630
  self.class.const_get(*const_args)
1573
1631
  else
1574
1632
  ancestors = self.class.name.to_s.split("::")
@@ -1584,6 +1642,13 @@ module ActiveResource
1584
1642
  end
1585
1643
  end
1586
1644
 
1645
+ def const_valid?(*const_args)
1646
+ self.class.const_defined?(*const_args)
1647
+ true
1648
+ rescue NameError
1649
+ false
1650
+ end
1651
+
1587
1652
  # Create and return a class definition for a resource inside the current resource
1588
1653
  def create_resource_for(resource_name)
1589
1654
  resource = self.class.const_set(resource_name, Class.new(ActiveResource::Base))