diff --git a/activerecord/lib/active_record/autosave_association.rb b/activerecord/lib/active_record/autosave_association.rb index d6c7c298735a7..bb0d75656b18a 100644 --- a/activerecord/lib/active_record/autosave_association.rb +++ b/activerecord/lib/active_record/autosave_association.rb @@ -361,9 +361,7 @@ def normalize_reflection_attribute(indexed_attribute, reflection, index, attribu # Is used as a before_save callback to check while saving a collection # association whether or not the parent was a new record before saving. def before_save_collection_association - unless defined?(@new_record_before_save) - @new_record_before_save = new_record? - end + @new_record_before_save ||= new_record? end def after_save_collection_association diff --git a/activerecord/test/cases/autosave_association_test.rb b/activerecord/test/cases/autosave_association_test.rb index 4f988e20509a7..1b423b6df81ac 100644 --- a/activerecord/test/cases/autosave_association_test.rb +++ b/activerecord/test/cases/autosave_association_test.rb @@ -739,6 +739,15 @@ def test_replace_on_new_object assert_equal 2, firm.clients.length assert_includes firm.clients, Client.find_by_name("New Client") end + + def test_replace_on_duplicated_object + firm = Firm.create!("name" => "New Firm").dup + firm.clients = [companies(:second_client), Client.new("name" => "New Client")] + assert firm.save + firm.reload + assert_equal 2, firm.clients.length + assert_includes firm.clients, Client.find_by_name("New Client") + end end class TestDefaultAutosaveAssociationOnNewRecord < ActiveRecord::TestCase diff --git a/activerecord/test/cases/transactions_test.rb b/activerecord/test/cases/transactions_test.rb index b5c1cac3d9e1e..956d10653f651 100644 --- a/activerecord/test/cases/transactions_test.rb +++ b/activerecord/test/cases/transactions_test.rb @@ -77,6 +77,20 @@ def test_rollback_dirty_changes_then_retry_save_on_new_record assert_equal topic.title, topic.reload.title end + def test_rollback_dirty_changes_then_retry_save_on_new_record_with_autosave_association + author = Author.new(name: "DHH") + book = Book.create! + author.books << book + + author.transaction do + author.save! + raise ActiveRecord::Rollback + end + + author.save! + assert_equal author, book.reload.author + end + def test_persisted_in_a_model_with_custom_primary_key_after_failed_save movie = Movie.create assert_not_predicate movie, :persisted?