Match destroyed_by_association for has_one to has_many

When a has_many association is destroyed by `dependent: destroy`,
destroyed_by_association is set to the reflection, and this can be
checked in callbacks.  This matches that behaviour for has_one
associations.
This commit is contained in:
Lisa Ugray 2017-07-19 14:56:35 -04:00
parent 1f7f872ac6
commit cb8d890991
3 changed files with 42 additions and 0 deletions

View File

@ -1,3 +1,9 @@
* When a `has_one` association is destroyed by `dependent: destroy`,
`destroyed_by_association` will now be set to the reflection, matching the
behaviour of `has_many` associations.
*Lisa Ugray*
* Fix `unscoped(where: [columns])` removing the wrong bind values
When the `where` is called on a relation after a `or`, unscoping the column of that later `where` removed

View File

@ -56,6 +56,7 @@ module ActiveRecord
when :delete
target.delete
when :destroy
target.destroyed_by_association = reflection
target.destroy
when :nullify
target.update_columns(reflection.foreign_key => nil) if target.persisted?
@ -78,6 +79,7 @@ module ActiveRecord
when :delete
target.delete
when :destroy
target.destroyed_by_association = reflection
target.destroy
else
nullify_owner_attributes(target)

View File

@ -688,4 +688,38 @@ class HasOneAssociationsTest < ActiveRecord::TestCase
SpecialAuthor.joins(book: :subscription).where.not(where_clause)
end
end
class DestroyByParentBook < ActiveRecord::Base
self.table_name = "books"
belongs_to :author, class_name: "DestroyByParentAuthor"
before_destroy :dont, unless: :destroyed_by_association
def dont
throw(:abort)
end
end
class DestroyByParentAuthor < ActiveRecord::Base
self.table_name = "authors"
has_one :book, class_name: "DestroyByParentBook", foreign_key: "author_id", dependent: :destroy
end
test "destroyed_by_association set in child destroy callback on parent destroy" do
author = DestroyByParentAuthor.create!(name: "Test")
book = DestroyByParentBook.create!(author: author)
author.destroy
assert_not DestroyByParentBook.exists?(book.id)
end
test "destroyed_by_association set in child destroy callback on replace" do
author = DestroyByParentAuthor.create!(name: "Test")
book = DestroyByParentBook.create!(author: author)
author.book = DestroyByParentBook.create!
author.save!
assert_not DestroyByParentBook.exists?(book.id)
end
end