From bca5499e912b12e8c87214ad08ead88b9ecef992 Mon Sep 17 00:00:00 2001 From: Nobuhiro IMAI Date: Fri, 23 Oct 2009 18:46:27 +0900 Subject: [PATCH 1/2] [nested attributes]: use existing record on one to one association --- .../lib/active_record/nested_attributes.rb | 8 +++- activerecord/test/cases/nested_attributes_test.rb | 34 ++++++++++++++++++++ 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/activerecord/lib/active_record/nested_attributes.rb b/activerecord/lib/active_record/nested_attributes.rb index edcf547..d69f375 100644 --- a/activerecord/lib/active_record/nested_attributes.rb +++ b/activerecord/lib/active_record/nested_attributes.rb @@ -223,7 +223,7 @@ module ActiveRecord def accepts_nested_attributes_for(*attr_names) options = { :allow_destroy => false } options.update(attr_names.extract_options!) - options.assert_valid_keys(:allow_destroy, :reject_if, :limit) + options.assert_valid_keys(:allow_destroy, :reject_if, :limit, :use_existing_record) attr_names.each do |association_name| if reflection = reflect_on_association(association_name) @@ -295,6 +295,10 @@ module ActiveRecord options = self.nested_attributes_options[association_name] attributes = attributes.with_indifferent_access + if options[:use_existing_record] and attributes['id'].blank? + existing_record = __send__(association_name) + attributes['id'] = existing_record.id if existing_record + end if attributes['id'].blank? unless reject_new_record?(association_name, attributes) method = "build_#{association_name}" @@ -304,7 +308,7 @@ module ActiveRecord raise ArgumentError, "Cannot build association #{association_name}. Are you trying to build a polymorphic one-to-one association?" end end - elsif (existing_record = send(association_name)) && existing_record.id.to_s == attributes['id'].to_s + elsif (existing_record ||= send(association_name)) && existing_record.id.to_s == attributes['id'].to_s assign_to_or_mark_for_destruction(existing_record, attributes, options[:allow_destroy]) end end diff --git a/activerecord/test/cases/nested_attributes_test.rb b/activerecord/test/cases/nested_attributes_test.rb index 53fd168..74ada18 100644 --- a/activerecord/test/cases/nested_attributes_test.rb +++ b/activerecord/test/cases/nested_attributes_test.rb @@ -245,6 +245,23 @@ class TestNestedAttributesOnAHasOneAssociation < ActiveRecord::TestCase def test_should_automatically_enable_autosave_on_the_association assert Pirate.reflect_on_association(:ship).options[:autosave] end + + def test_should_update_existing_record_if_specified + Pirate.accepts_nested_attributes_for :ship, :use_existing_record => true + + ship_id = @ship.id + assert_no_difference('Ship.count') do + @pirate.update_attributes!(:ship_attributes => {:name => 'Thousand Sunny'}) + end + assert_equal 'Thousand Sunny', Ship.find(ship_id).name + @ship.destroy + @pirate.reload.ship_attributes = {:name => 'Big Top'} + assert_equal true, @pirate.ship.new_record?, "should be built now" + assert_difference('Ship.count') do + @pirate.save! + end + assert_equal 'Big Top', @pirate.ship(true).name + end end class TestNestedAttributesOnABelongsToAssociation < ActiveRecord::TestCase @@ -362,6 +379,23 @@ class TestNestedAttributesOnABelongsToAssociation < ActiveRecord::TestCase def test_should_automatically_enable_autosave_on_the_association assert Ship.reflect_on_association(:pirate).options[:autosave] end + + def test_should_update_existing_record_if_specified + Ship.accepts_nested_attributes_for :pirate, :use_existing_record => true + + pirate_id = @pirate.id + assert_no_difference('Pirate.count') do + @ship.update_attributes!(:pirate_attributes => {:catchphrase => 'from a spoon'}) + end + assert_equal 'from a spoon', Pirate.find(pirate_id).catchphrase + @pirate.destroy + @ship.reload.pirate_attributes = {:catchphrase => 'to Space Battleship'} + assert_equal true, @ship.pirate.new_record?, "should be built now" + assert_difference('Pirate.count') do + @ship.save! + end + assert_equal 'to Space Battleship', @ship.pirate(true).catchphrase + end end module NestedAttributesOnACollectionAssociationTests -- 1.6.5