Skip to content

Commit

Permalink
Allow associations to be autosaved multiple times
Browse files Browse the repository at this point in the history
Since 901d62c, associations can only be
autosaved once: after a record has been saved, `@new_record_before_save`
will always be false. This assumes that records only transition to being
persisted once, but there are two cases where it happens multiple times:
when the transaction that saved the record is rolled back, and when the
persisted record is later duplicated.
  • Loading branch information
eugeneius committed May 3, 2020
1 parent d1d98f3 commit 8fd4189
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 3 deletions.
4 changes: 1 addition & 3 deletions activerecord/lib/active_record/autosave_association.rb
Original file line number Diff line number Diff line change
Expand Up @@ -365,9 +365,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
Expand Down
9 changes: 9 additions & 0 deletions activerecord/test/cases/autosave_association_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
14 changes: 14 additions & 0 deletions activerecord/test/cases/transactions_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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?
Expand Down

0 comments on commit 8fd4189

Please sign in to comment.