Skip to content

Commit 1918b12

Browse files
committed
Fix wrong behavior where associations with dependent: :destroy options
was using nullify strategy This caused a regression in applications trying to upgrade. Also if the user set the dependent option as destroy he expects to get the records removed from the database.
1 parent d9e7050 commit 1918b12

File tree

3 files changed

+7
-10
lines changed

3 files changed

+7
-10
lines changed

activerecord/CHANGELOG.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -545,11 +545,11 @@
545545
Method `delete_all` should not be invoking callbacks and this
546546
feature was deprecated in Rails 4.0. This is being removed.
547547
`delete_all` will continue to honor the `:dependent` option. However
548-
if `:dependent` value is `:destroy` then the default deletion
548+
if `:dependent` value is `:destroy` then the `:delete_all` deletion
549549
strategy for that collection will be applied.
550550

551551
User can also force a deletion strategy by passing parameter to
552-
`delete_all`. For example you can do `@post.comments.delete_all(:nullify)` .
552+
`delete_all`. For example you can do `@post.comments.delete_all(:nullify)`.
553553

554554
*Neeraj Singh*
555555

activerecord/lib/active_record/associations/collection_association.rb

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ def transaction(*args)
151151

152152
# Removes all records from the association without calling callbacks
153153
# on the associated records. It honors the `:dependent` option. However
154-
# if the `:dependent` value is `:destroy` then in that case the default
154+
# if the `:dependent` value is `:destroy` then in that case the `:delete_all`
155155
# deletion strategy for the association is applied.
156156
#
157157
# You can force a particular deletion strategy by passing a parameter.
@@ -170,9 +170,7 @@ def delete_all(dependent = nil)
170170
dependent = if dependent.present?
171171
dependent
172172
elsif options[:dependent] == :destroy
173-
# since delete_all should not invoke callbacks so use the default deletion strategy
174-
# for :destroy
175-
reflection.is_a?(ActiveRecord::Reflection::ThroughReflection) ? :delete_all : :nullify
173+
:delete_all
176174
else
177175
options[:dependent]
178176
end

activerecord/test/cases/associations/has_many_associations_test.rb

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,11 +101,10 @@ def test_create_from_association_with_nil_values_should_work
101101
end
102102

103103
def test_do_not_call_callbacks_for_delete_all
104-
bulb_count = Bulb.count
105104
car = Car.create(:name => 'honda')
106105
car.funky_bulbs.create!
107106
assert_nothing_raised { car.reload.funky_bulbs.delete_all }
108-
assert_equal bulb_count + 1, Bulb.count, "bulbs should have been deleted using :nullify strategey"
107+
assert_equal 0, Bulb.count, "bulbs should have been deleted using :delete_all strategey"
109108
end
110109

111110
def test_building_the_associated_object_with_implicit_sti_base_class
@@ -864,15 +863,15 @@ def test_clearing_a_dependent_association_collection
864863
assert_equal 1, firm.dependent_clients_of_firm.size
865864
assert_equal 1, Client.find_by_id(client_id).client_of
866865

867-
# :nullify is called on each client
866+
# :delete_all is called on each client since the dependent options is :destroy
868867
firm.dependent_clients_of_firm.clear
869868

870869
assert_equal 0, firm.dependent_clients_of_firm.size
871870
assert_equal 0, firm.dependent_clients_of_firm(true).size
872871
assert_equal [], Client.destroyed_client_ids[firm.id]
873872

874873
# Should be destroyed since the association is dependent.
875-
assert_nil Client.find_by_id(client_id).client_of
874+
assert_nil Client.find_by_id(client_id)
876875
end
877876

878877
def test_delete_all_with_option_delete_all

0 commit comments

Comments
 (0)