Permalink
Browse files

Allow ActiveResource to work with non-generated ids [#5660 state:reso…

…lved]

This commit updates new? so that it knows whether or not the record was actually new or not, and doesn't rely solely on the presence of id. This enables the ability to set a custom primary_key that is not autogenerated by the server.

Signed-off-by: José Valim <jose.valim@gmail.com>
  • Loading branch information...
1 parent 1b7d30b commit ee5ef67c443407f616feef3a8cade8ba3a9d6ef0 @jacquescrocker jacquescrocker committed with josevalim Sep 19, 2010
@@ -886,7 +886,7 @@ def instantiate_collection(collection, prefix_options = {})
end
def instantiate_record(record, prefix_options = {})
- new(record).tap do |resource|
+ new(record, true).tap do |resource|
resource.prefix_options = prefix_options
end
end
@@ -959,9 +959,10 @@ def known_attributes
#
# my_other_course = Course.new(:name => "Philosophy: Reason and Being", :lecturer => "Ralph Cling")
# my_other_course.save
- def initialize(attributes = {})
+ def initialize(attributes = {}, persisted = false)
@attributes = {}.with_indifferent_access
@prefix_options = {}
+ @persisted = persisted
load(attributes)
end
@@ -1011,7 +1012,7 @@ def clone
# is_new.new? # => false
#
def new?
- id.nil?
+ !persisted?
end
alias :new_record? :new?
@@ -1028,7 +1029,7 @@ def new?
# not_persisted.persisted? # => true
#
def persisted?
- !new?
+ @persisted
end
# Gets the <tt>\id</tt> attribute of the resource.
@@ -1317,6 +1318,7 @@ def create
def load_attributes_from_response(response)
if !response['Content-Length'].blank? && response['Content-Length'] != "0" && !response.body.nil? && response.body.strip.size > 0
load(self.class.format.decode(response.body))
+ @persisted = true
end
end
@@ -91,7 +91,7 @@ def test_custom_new_element_method
201, {'Location' => '/people/1/addresses/2.xml'}),
addy.post(:link)
- matz = Person.new(:id => 1, :name => 'Matz')
+ matz = Person.find(1)
assert_equal ActiveResource::Response.new(@matz, 201), matz.post(:register)
end
@@ -5,6 +5,8 @@
require "fixtures/sound"
require "fixtures/beast"
require "fixtures/proxy"
+require "fixtures/address"
+require "fixtures/subscription_plan"
require 'active_support/json'
require 'active_support/ordered_hash'
require 'active_support/core_ext/hash/conversions'
@@ -1034,4 +1036,51 @@ def test_load_yaml_array
end
end
end
+
+ def test_with_custom_formatter
+ @addresses = [{:id => "1", :street => "1 Infinite Loop", :city => "Cupertino", :state => "CA"}].to_xml(:root => 'addresses')
+
+ ActiveResource::HttpMock.respond_to do |mock|
+ mock.get "/addresses.xml", {}, @addresses, 200
+ end
+
+ # late bind the site
+ AddressResource.site = "http://localhost"
+ addresses = AddressResource.find(:all)
+
+ assert_equal "Cupertino, CA", addresses.first.city_state
+ end
+
+ def test_create_with_custom_primary_key
+ silver_plan = {:code => "silver", :price => 5.00}.to_xml(:root => "plan")
+
+ ActiveResource::HttpMock.respond_to do |mock|
+ mock.post "/plans.xml", {}, silver_plan, 201, 'Location' => '/plans/silver.xml'
+ end
+
+ plan = SubscriptionPlan.new(:code => "silver", :price => 5.00)
+ assert plan.new?
+
+ plan.save!
+ assert !plan.new?
+ end
+
+ def test_update_with_custom_primary_key
+ silver_plan = {:code => "silver", :price => 5.00}.to_xml(:root => "plan")
+ silver_plan_updated = {:code => "silver", :price => 10.00}.to_xml(:root => "plan")
+
+ ActiveResource::HttpMock.respond_to do |mock|
+ mock.get "/plans/silver.xml", {}, silver_plan
+ mock.put "/plans/silver.xml", {}, silver_plan_updated, 201, 'Location' => '/plans/silver.xml'
+ end
+
+ plan = SubscriptionPlan.find("silver")
+ assert !plan.new?
+ assert 5.00, plan.price
+
+ # update price
+ plan.price = 10.00
+ plan.save!
+ assert 10.00, plan.price
+ end
end
@@ -0,0 +1,19 @@
+# turns everyting into the same object
+class AddressXMLFormatter
+ include ActiveResource::Formats::XmlFormat
+
+ def decode(xml)
+ data = ActiveResource::Formats::XmlFormat.decode(xml)
+ # process address fields
+ data.each do |address|
+ address['city_state'] = "#{address['city']}, #{address['state']}"
+ end
+ data
+ end
+
+end
+
+class AddressResource < ActiveResource::Base
+ self.element_name = "address"
+ self.format = AddressXMLFormatter.new
+end
@@ -0,0 +1,5 @@
+class SubscriptionPlan < ActiveResource::Base
+ self.site = "http://37s.sunrise.i:3000"
+ self.element_name = 'plan'
+ self.primary_key = :code
+end

0 comments on commit ee5ef67

Please sign in to comment.