From eb22c248de8a867d3ffef09ff8575409918c9011 Mon Sep 17 00:00:00 2001 From: Lawrence Pit Date: Thu, 7 Jan 2010 19:53:15 +0100 Subject: [PATCH] Exclude unchanged records from the collection being considered for autosave. [#2578 state:resolved] Signed-off-by: Eloy Duran --- .../lib/active_record/autosave_association.rb | 6 +++--- .../test/cases/autosave_association_test.rb | 13 ++++--------- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/activerecord/lib/active_record/autosave_association.rb b/activerecord/lib/active_record/autosave_association.rb index aad925c79968a..4c6489d25c10f 100644 --- a/activerecord/lib/active_record/autosave_association.rb +++ b/activerecord/lib/active_record/autosave_association.rb @@ -225,10 +225,10 @@ def marked_for_destruction? def associated_records_to_validate_or_save(association, new_record, autosave) if new_record association - elsif association.loaded? - autosave ? association : association.select { |record| record.new_record? } + elsif autosave + association.target.select { |record| record.new_record? || record.changed? || record.marked_for_destruction? } else - autosave ? association.target : association.target.select { |record| record.new_record? } + association.target.select { |record| record.new_record? } end end diff --git a/activerecord/test/cases/autosave_association_test.rb b/activerecord/test/cases/autosave_association_test.rb index 7581c3f28dbdb..87c124c1d16b6 100644 --- a/activerecord/test/cases/autosave_association_test.rb +++ b/activerecord/test/cases/autosave_association_test.rb @@ -694,23 +694,18 @@ def save(*args) define_method("test_should_rollback_destructions_if_an_exception_occurred_while_saving_#{association_name}") do 2.times { |i| @pirate.send(association_name).create!(:name => "#{association_name}_#{i}") } - before = @pirate.send(association_name).map { |c| c } + before = @pirate.send(association_name).map { |c| c.mark_for_destruction ; c } - # Stub the save method of the first child to destroy and the second to raise an exception - class << before.first - def save(*args) - super - destroy - end - end + # Stub the destroy method of the the second child to raise an exception class << before.last - def save(*args) + def destroy(*args) super raise 'Oh noes!' end end assert_raise(RuntimeError) { assert !@pirate.save } + assert before.first.frozen? # the first child was indeed destroyed assert_equal before, @pirate.reload.send(association_name) end