Confirm a record has not already been destroyed before decrementing

counter cache

At present, calling destroy multiple times on the same record results
in the belongs_to counter cache being decremented multiple times. With
this change the record is checked for whether it is already destroyed
prior to decrementing the counter cache.
This commit is contained in:
Ben Tucker 2013-05-06 18:31:20 -04:00
parent f7f8b7ccfc
commit 228720ef19
3 changed files with 27 additions and 1 deletions

@ -1,3 +1,7 @@
* Confirm a record has not already been destroyed before decrementing counter cache.
*Ben Tucker*
* Mute `psql` output when running rake db:schema:load.
*Godfrey Chan*

@ -34,7 +34,9 @@ def belongs_to_counter_cache_after_create_for_#{name}
def belongs_to_counter_cache_before_destroy_for_#{name}
unless destroyed_by_association && destroyed_by_association.foreign_key.to_sym == #{foreign_key.to_sym.inspect}
record = #{name}
record.class.decrement_counter(:#{cache_column}, record.id) unless record.nil?
if record && !self.destroyed?
record.class.decrement_counter(:#{cache_column}, record.id)
end
end
end

@ -414,6 +414,26 @@ def test_counter_cache
assert_equal 15, topic.replies.size
end
def test_counter_cache_double_destroy
topic = Topic.create :title => "Zoom-zoom-zoom"
5.times do
topic.replies.create(:title => "re: zoom", :content => "speedy quick!")
end
assert_equal 5, topic.reload[:replies_count]
assert_equal 5, topic.replies.size
reply = topic.replies.first
reply.destroy
assert_equal 4, topic.reload[:replies_count]
reply.destroy
assert_equal 4, topic.reload[:replies_count]
assert_equal 4, topic.replies.size
end
def test_custom_counter_cache
reply = Reply.create(:title => "re: zoom", :content => "speedy quick!")
assert_equal 0, reply[:replies_count]