From 47174791da61f5a6980c9f7c3acc96b1d6b402a8 Mon Sep 17 00:00:00 2001 From: Szetobo Date: Mon, 12 Jul 2010 05:32:51 +0800 Subject: [PATCH] [#5053: patch] --- .../associations/association_collection.rb | 14 ++++++++++---- activerecord/test/cases/nested_attributes_test.rb | 14 ++++++++++++++ 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/activerecord/lib/active_record/associations/association_collection.rb b/activerecord/lib/active_record/associations/association_collection.rb index 615b7d2..a67e6e2 100644 --- a/activerecord/lib/active_record/associations/association_collection.rb +++ b/activerecord/lib/active_record/associations/association_collection.rb @@ -393,11 +393,11 @@ module ActiveRecord if @target.is_a?(Array) && @target.any? @target = find_target.map do |f| i = @target.index(f) - t = @target.delete_at(i) if i - if t && t.changed? + if i + t = @target.delete_at(i) + t.attributes = f.attributes.except(*(t.changes.keys + (f.attribute_names - t.attribute_names))) t else - f.mark_for_destruction if t && t.marked_for_destruction? f end end + @target @@ -479,7 +479,13 @@ module ActiveRecord callback(:before_add, record) yield(record) if block_given? @target ||= [] unless loaded? - @target << record unless @reflection.options[:uniq] && @target.include?(record) + unless @reflection.options[:uniq] && @target.include?(record) + if index = @target.index(record) + @target[index] = record + else + @target << record + end + end callback(:after_add, record) set_inverse_instance(record, @owner) record diff --git a/activerecord/test/cases/nested_attributes_test.rb b/activerecord/test/cases/nested_attributes_test.rb index c9ea0d8..89ae17f 100644 --- a/activerecord/test/cases/nested_attributes_test.rb +++ b/activerecord/test/cases/nested_attributes_test.rb @@ -811,6 +811,20 @@ class TestHasManyAutosaveAssociationWhichItselfHasAutosaveAssociations < ActiveR @part = @ship.parts.create!(:name => "Mast") @trinket = @part.trinkets.create!(:name => "Necklace") end + + test "if association is not loaded and I am saving a child then in memory record should be used" do + @ship.parts_attributes=[{:id => @part.id,:name =>'Deck'}] + assert_equal 1, @ship.parts.proxy_target.size + assert_equal 'Deck', @ship.parts[0].name + end + + test "if association is not loaded and child doesn't change and I am saving a grandchild then in memory record should be used" do + @ship.parts_attributes=[{:id => @part.id,:trinkets_attributes =>[{:id => @trinket.id, :name => 'Ruby'}]}] + assert_equal 1, @ship.parts.proxy_target.size + assert_equal 'Mast', @ship.parts[0].name + assert_equal 1, @ship.parts[0].trinkets.proxy_target.size + assert_equal 'Ruby', @ship.parts[0].trinkets[0].name + end test "when grandchild changed in memory, saving parent should save grandchild" do @trinket.name = "changed" -- 1.7.0.4