Skip to content

Commit

Permalink
Allow ActiveResource to work with non-generated ids [#5660 state:reso…
Browse files Browse the repository at this point in the history
…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
Jacques Crocker authored and josevalim committed Sep 25, 2010
1 parent 1b7d30b commit ee5ef67
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 5 deletions.
10 changes: 6 additions & 4 deletions activeresource/lib/active_resource/base.rb
Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -1011,7 +1012,7 @@ def clone
# is_new.new? # => false
#
def new?
id.nil?
!persisted?
end
alias :new_record? :new?

Expand All @@ -1028,7 +1029,7 @@ def new?
# not_persisted.persisted? # => true
#
def persisted?
!new?
@persisted
end

# Gets the <tt>\id</tt> attribute of the resource.
Expand Down Expand Up @@ -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

Expand Down
2 changes: 1 addition & 1 deletion activeresource/test/cases/base/custom_methods_test.rb
Expand Up @@ -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

Expand Down
49 changes: 49 additions & 0 deletions activeresource/test/cases/base_test.rb
Expand Up @@ -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'
Expand Down Expand Up @@ -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
19 changes: 19 additions & 0 deletions activeresource/test/fixtures/address.rb
@@ -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
5 changes: 5 additions & 0 deletions activeresource/test/fixtures/subscription_plan.rb
@@ -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.