Skip to content
This repository
Browse code

Remove explicit prefix_options parameter for ActiveResource::Base#ini…

…tialize. Allow ActiveResource::Base.delete with custom prefix. Add ActiveResource::Base#dup [Rick]

git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@6568 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
  • Loading branch information...
commit 208d12d15d809391abee90242effd53e3f7e9821 1 parent fe21868
risk danger olson authored April 24, 2007
7  activeresource/CHANGELOG
... ...
@@ -1,5 +1,12 @@
1 1
 *SVN*
2 2
 
  3
+* Remove explicit prefix_options parameter for ActiveResource::Base#initialize. [Rick]
  4
+  ActiveResource splits the prefix_options from it automatically.
  5
+
  6
+* Allow ActiveResource::Base.delete with custom prefix. [Rick]
  7
+
  8
+* Add ActiveResource::Base#dup [Rick]
  9
+
3 10
 * Fixed constant warning when fetching the same object multiple times [DHH]
4 11
 
5 12
 * Added that saves which get a body response (and not just a 201) will use that response to update themselves [DHH]
87  activeresource/lib/active_resource/base.rb
@@ -41,10 +41,16 @@ def connection(refresh = false)
41 41
       def prefix(options={})
42 42
         default = site.path
43 43
         default << '/' unless default[-1..-1] == '/'
  44
+        # generate the actual method based on the current site path
44 45
         self.prefix = default
45 46
         prefix(options)
46 47
       end
47 48
 
  49
+      def prefix_source
  50
+        prefix # generate #prefix and #prefix_source methods first
  51
+        prefix_source
  52
+      end
  53
+
48 54
       # Sets the resource prefix
49 55
       #  prefix/collectionname/1.xml
50 56
       def prefix=(value = '/')
@@ -67,12 +73,26 @@ def prefix(options={}) "#{prefix_call}" end
67 73
       alias_method :set_element_name, :element_name=  #:nodoc:
68 74
       alias_method :set_collection_name, :collection_name=  #:nodoc:
69 75
 
70  
-      def element_path(id, options = {})
71  
-        "#{prefix(options)}#{collection_name}/#{id}.xml#{query_string(options)}"
  76
+      # Gets the element path for the given ID.  If no query_options are given, they are split from the prefix options:
  77
+      #
  78
+      # Post.element_path(1) # => /posts/1.xml
  79
+      # Comment.element_path(1, :post_id => 5) # => /posts/5/comments/1.xml
  80
+      # Comment.element_path(1, :post_id => 5, :active => 1) # => /posts/5/comments/1.xml?active=1
  81
+      # Comment.element_path(1, {:post_id => 5}, {:active => 1}) # => /posts/5/comments/1.xml?active=1
  82
+      def element_path(id, prefix_options = {}, query_options = nil)
  83
+        prefix_options, query_options = split_options(prefix_options) if query_options.nil?
  84
+        "#{prefix(prefix_options)}#{collection_name}/#{id}.xml#{query_string(query_options)}"
72 85
       end
73 86
 
74  
-      def collection_path(options = {}) 
75  
-        "#{prefix(options)}#{collection_name}.xml#{query_string(options)}"
  87
+      # Gets the collection path.  If no query_options are given, they are split from the prefix options:
  88
+      #
  89
+      # Post.collection_path # => /posts.xml
  90
+      # Comment.collection_path(:post_id => 5) # => /posts/5/comments.xml
  91
+      # Comment.collection_path(:post_id => 5, :active => 1) # => /posts/5/comments.xml?active=1
  92
+      # Comment.collection_path({:post_id => 5}, {:active => 1}) # => /posts/5/comments.xml?active=1
  93
+      def collection_path(prefix_options = {}, query_options = nil)
  94
+        prefix_options, query_options = split_options(prefix_options) if query_options.nil?
  95
+        "#{prefix(prefix_options)}#{collection_name}.xml#{query_string(query_options)}"
76 96
       end
77 97
 
78 98
       alias_method :set_primary_key, :primary_key=  #:nodoc:
@@ -88,8 +108,8 @@ def collection_path(options = {})
88 108
       # has not been saved then <tt>resource.valid?</tt> will return <tt>false</tt>,
89 109
       # while <tt>resource.new?</tt> will still return <tt>true</tt>.
90 110
       #      
91  
-      def create(attributes = {}, prefix_options = {})
92  
-        returning(self.new(attributes, prefix_options)) { |res| res.save }        
  111
+      def create(attributes = {})
  112
+        returning(self.new(attributes)) { |res| res.save }        
93 113
       end
94 114
 
95 115
       # Core method for finding resources.  Used similarly to ActiveRecord's find method.
@@ -106,8 +126,8 @@ def find(*arguments)
106 126
         end
107 127
       end
108 128
 
109  
-      def delete(id)
110  
-        connection.delete(element_path(id))
  129
+      def delete(id, options = {})
  130
+        connection.delete(element_path(id, options))
111 131
       end
112 132
 
113 133
       # Evalutes to <tt>true</tt> if the resource is found.
@@ -120,14 +140,22 @@ def exists?(id, options = {})
120 140
       private
121 141
         # Find every resource.
122 142
         def find_every(options)
123  
-          collection = connection.get(collection_path(options)) || []
124  
-          collection.collect! { |element| new(element) }
  143
+          prefix_options, query_options = split_options(options)
  144
+          collection = connection.get(collection_path(prefix_options, query_options)) || []
  145
+          collection.collect! do |element|
  146
+            returning new(element.merge(prefix_options)) do |resource|
  147
+              resource.prefix_options = prefix_options
  148
+            end
  149
+          end
125 150
         end
126 151
 
127 152
         # Find a single resource.
128 153
         #  { :person => person1 }
129 154
         def find_single(scope, options)
130  
-          new(connection.get(element_path(scope, options)), options)
  155
+          prefix_options, query_options = split_options(options)
  156
+          returning new(connection.get(element_path(scope, prefix_options, query_options))) do |resource|
  157
+            resource.prefix_options = prefix_options
  158
+          end
131 159
         end
132 160
 
133 161
         # Accepts a URI and creates the site URI from that.
@@ -135,25 +163,34 @@ def create_site_uri_from(site)
135 163
           site.is_a?(URI) ? site.dup : URI.parse(site)
136 164
         end
137 165
 
  166
+        # contains a set of the current prefix parameters.
138 167
         def prefix_parameters
139 168
           @prefix_parameters ||= prefix_source.scan(/:\w+/).map { |key| key[1..-1].to_sym }.to_set
140 169
         end
141 170
 
142 171
         # Builds the query string for the request.
143 172
         def query_string(options)
144  
-          # Omit parameters which appear in the URI path.
145  
-          query_params = options.reject { |key, value| prefix_parameters.include?(key) }
146  
-          "?#{query_params.to_query}" unless query_params.empty? 
  173
+          "?#{options.to_query}" unless options.empty? 
  174
+        end
  175
+
  176
+        # split an option hash into two hashes, one containing the prefix options, 
  177
+        # and the other containing the leftovers.
  178
+        def split_options(options = {})
  179
+          prefix_options = {}; query_options = {}
  180
+          options.each do |key, value|
  181
+            (prefix_parameters.include?(key) ? prefix_options : query_options)[key] = value
  182
+          end
  183
+          [prefix_options, query_options]
147 184
         end
148 185
     end
149 186
 
150 187
     attr_accessor :attributes #:nodoc:
151 188
     attr_accessor :prefix_options #:nodoc:
152 189
 
153  
-    def initialize(attributes = {}, prefix_options = {})
154  
-      @attributes = {}
  190
+    def initialize(attributes = {})
  191
+      @attributes     = {}
  192
+      @prefix_options = {}
155 193
       load(attributes)
156  
-      @prefix_options = prefix_options
157 194
     end
158 195
 
159 196
     # Is the resource a new object?
@@ -186,6 +223,13 @@ def eql?(other)
186 223
     def hash
187 224
       id.hash
188 225
     end
  226
+    
  227
+    def dup
  228
+      returning new do |resource|
  229
+        resource.attributes     = @attributes
  230
+        resource.prefix_options = @prefix_options
  231
+      end
  232
+    end
189 233
 
190 234
     # Delegates to +create+ if a new object, +update+ if its old. If the response to the save includes a body,
191 235
     # it will be assumed that this body is XML for the final object as it looked after the save (which would include
@@ -218,6 +262,7 @@ def reload
218 262
     # resources.
219 263
     def load(attributes)
220 264
       raise ArgumentError, "expected an attributes Hash, got #{attributes.inspect}" unless attributes.is_a?(Hash)
  265
+      @prefix_options, attributes = split_options(attributes)
221 266
       attributes.each do |key, value|
222 267
         @attributes[key.to_s] =
223 268
           case value
@@ -227,8 +272,6 @@ def load(attributes)
227 272
             when Hash
228 273
               resource = find_or_create_resource_for(key)
229 274
               resource.new(value)
230  
-            when ActiveResource::Base
231  
-              value.class.new(value.attributes, value.prefix_options)
232 275
             else
233 276
               value.dup rescue value
234 277
           end
@@ -243,7 +286,7 @@ def connection(refresh = false)
243 286
 
244 287
       # Update the resource on the remote service.
245 288
       def update
246  
-        connection.put(element_path, to_xml)
  289
+        connection.put(element_path(prefix_options), to_xml)
247 290
       end
248 291
 
249 292
       # Create (i.e., save to the remote service) the new resource.
@@ -287,6 +330,10 @@ def find_or_create_resource_for(name)
287 330
         resource
288 331
       end
289 332
 
  333
+      def split_options(options = {})
  334
+        self.class.send(:split_options, options)
  335
+      end
  336
+
290 337
       def method_missing(method_symbol, *arguments) #:nodoc:
291 338
         method_name = method_symbol.to_s
292 339
 
28  activeresource/test/base_test.rb
@@ -112,6 +112,10 @@ def test_custom_element_path_with_parameters
112 112
     assert_equal '/people/1/addresses/1.xml?type%5B%5D=work&type%5B%5D=play+time', StreetAddress.element_path(1, :person_id => 1, :type => ['work', 'play time'])
113 113
   end
114 114
 
  115
+  def test_custom_element_path_with_prefix_and_parameters
  116
+    assert_equal '/people/1/addresses/1.xml?type=work', StreetAddress.element_path(1, {:person_id => 1}, {:type => 'work'})
  117
+  end
  118
+
115 119
   def test_custom_collection_path
116 120
     assert_equal '/people/1/addresses.xml', StreetAddress.collection_path(:person_id => 1)
117 121
   end
@@ -120,6 +124,10 @@ def test_custom_collection_path_with_parameters
120 124
     assert_equal '/people/1/addresses.xml?type=work', StreetAddress.collection_path(:person_id => 1, :type => 'work')
121 125
   end
122 126
 
  127
+  def test_custom_collection_path_with_prefix_and_parameters
  128
+    assert_equal '/people/1/addresses.xml?type=work', StreetAddress.collection_path({:person_id => 1}, {:type => 'work'})
  129
+  end
  130
+
123 131
   def test_custom_element_name
124 132
     assert_equal 'address', StreetAddress.element_name
125 133
   end
@@ -207,7 +215,7 @@ def test_id_from_response
207 215
   end
208 216
 
209 217
   def test_create_with_custom_prefix
210  
-    matzs_house = StreetAddress.new({}, { :person_id => 1 })
  218
+    matzs_house = StreetAddress.new(:person_id => 1)
211 219
     matzs_house.save
212 220
     assert_equal '5', matzs_house.id
213 221
   end
@@ -272,11 +280,23 @@ def test_destroy_with_custom_prefix
272 280
     ActiveResource::HttpMock.respond_to do |mock|
273 281
       mock.get "/people/1/addresses/1.xml", {}, nil, 404
274 282
     end
275  
-    assert_raises(ActiveResource::ResourceNotFound) { StreetAddress.find(1, :person_id => 1).destroy }
  283
+    assert_raises(ActiveResource::ResourceNotFound) { StreetAddress.find(1, :person_id => 1) }
276 284
   end
277 285
 
278 286
   def test_delete
279 287
     assert Person.delete(1)
  288
+    ActiveResource::HttpMock.respond_to do |mock|
  289
+      mock.get "/people/1.xml", {}, nil, 404
  290
+    end
  291
+    assert_raises(ActiveResource::ResourceNotFound) { Person.find(1) }
  292
+  end
  293
+  
  294
+  def test_delete_with_custom_prefix
  295
+    assert StreetAddress.delete(1, :person_id => 1)
  296
+    ActiveResource::HttpMock.respond_to do |mock|
  297
+      mock.get "/people/1/addresses/1.xml", {}, nil, 404
  298
+    end
  299
+    assert_raises(ActiveResource::ResourceNotFound) { StreetAddress.find(1, :person_id => 1) }
280 300
   end
281 301
 
282 302
   def test_exists
@@ -297,8 +317,8 @@ def test_exists
297 317
 
298 318
     # Nested instance method.
299 319
     assert StreetAddress.find(1, :person_id => 1).exists?
300  
-    assert !StreetAddress.new({:id => 1}, {:person_id => 2}).exists?
301  
-    assert !StreetAddress.new({:id => 2}, {:person_id => 1}).exists?
  320
+    assert !StreetAddress.new({:id => 1, :person_id => 2}).exists?
  321
+    assert !StreetAddress.new({:id => 2, :person_id => 1}).exists?
302 322
   end
303 323
   
304 324
   def test_to_xml

0 notes on commit 208d12d

Please sign in to comment.
Something went wrong with that request. Please try again.