Commit 25d21185 by Ben A. Morgan Committed by GitHub

Merge pull request #390 from excid3/core

Fix counter cache with double destroy, really_destroy, and restore
parents 36adfecb 9ec5f94c
...@@ -76,6 +76,7 @@ module Paranoia ...@@ -76,6 +76,7 @@ module Paranoia
def destroy def destroy
transaction do transaction do
run_callbacks(:destroy) do run_callbacks(:destroy) do
@_disable_counter_cache = deleted?
result = delete result = delete
next result unless result && ActiveRecord::VERSION::STRING >= '4.2' next result unless result && ActiveRecord::VERSION::STRING >= '4.2'
each_counter_cached_associations do |association| each_counter_cached_associations do |association|
...@@ -84,6 +85,7 @@ module Paranoia ...@@ -84,6 +85,7 @@ module Paranoia
next unless send(association.reflection.name) next unless send(association.reflection.name)
association.decrement_counters association.decrement_counters
end end
@_disable_counter_cache = false
result result
end end
end end
...@@ -110,8 +112,15 @@ module Paranoia ...@@ -110,8 +112,15 @@ module Paranoia
# This only happened on Rails versions earlier than 4.1. # This only happened on Rails versions earlier than 4.1.
noop_if_frozen = ActiveRecord.version < Gem::Version.new("4.1") noop_if_frozen = ActiveRecord.version < Gem::Version.new("4.1")
if within_recovery_window?(recovery_window_range) && ((noop_if_frozen && !@attributes.frozen?) || !noop_if_frozen) if within_recovery_window?(recovery_window_range) && ((noop_if_frozen && !@attributes.frozen?) || !noop_if_frozen)
@_disable_counter_cache = !deleted?
write_attribute paranoia_column, paranoia_sentinel_value write_attribute paranoia_column, paranoia_sentinel_value
update_columns(paranoia_restore_attributes) update_columns(paranoia_restore_attributes)
each_counter_cached_associations do |association|
if send(association.reflection.name)
association.increment_counters
end
end
@_disable_counter_cache = false
end end
restore_associated_records(recovery_window_range) if opts[:recursive] restore_associated_records(recovery_window_range) if opts[:recursive]
end end
...@@ -140,6 +149,7 @@ module Paranoia ...@@ -140,6 +149,7 @@ module Paranoia
def really_destroy! def really_destroy!
transaction do transaction do
run_callbacks(:real_destroy) do run_callbacks(:real_destroy) do
@_disable_counter_cache = deleted?
dependent_reflections = self.class.reflections.select do |name, reflection| dependent_reflections = self.class.reflections.select do |name, reflection|
reflection.options[:dependent] == :destroy reflection.options[:dependent] == :destroy
end end
...@@ -163,6 +173,10 @@ module Paranoia ...@@ -163,6 +173,10 @@ module Paranoia
private private
def each_counter_cached_associations
!@_disable_counter_cache && defined?(super) ? super : []
end
def paranoia_restore_attributes def paranoia_restore_attributes
{ {
paranoia_column => paranoia_sentinel_value paranoia_column => paranoia_sentinel_value
......
...@@ -1003,6 +1003,44 @@ class ParanoiaTest < test_framework ...@@ -1003,6 +1003,44 @@ class ParanoiaTest < test_framework
assert related_model.instance_variable_get(:@after_destroy_callback_called) assert related_model.instance_variable_get(:@after_destroy_callback_called)
assert related_model.instance_variable_get(:@after_commit_on_destroy_callback_called) assert related_model.instance_variable_get(:@after_commit_on_destroy_callback_called)
end end
def test_counter_cache_column_on_double_destroy
parent_model_with_counter_cache_column = ParentModelWithCounterCacheColumn.create
related_model = parent_model_with_counter_cache_column.related_models.create
related_model.destroy
related_model.destroy
assert_equal 0, parent_model_with_counter_cache_column.reload.related_models_count
end
def test_counter_cache_column_on_double_restore
parent_model_with_counter_cache_column = ParentModelWithCounterCacheColumn.create
related_model = parent_model_with_counter_cache_column.related_models.create
related_model.destroy
related_model.restore
related_model.restore
assert_equal 1, parent_model_with_counter_cache_column.reload.related_models_count
end
def test_counter_cache_column_on_destroy_and_really_destroy
parent_model_with_counter_cache_column = ParentModelWithCounterCacheColumn.create
related_model = parent_model_with_counter_cache_column.related_models.create
related_model.destroy
related_model.really_destroy!
assert_equal 0, parent_model_with_counter_cache_column.reload.related_models_count
end
def test_counter_cache_column_on_restore
parent_model_with_counter_cache_column = ParentModelWithCounterCacheColumn.create
related_model = parent_model_with_counter_cache_column.related_models.create
related_model.destroy
assert_equal 0, parent_model_with_counter_cache_column.reload.related_models_count
related_model.restore
assert_equal 1, parent_model_with_counter_cache_column.reload.related_models_count
end
end end
private private
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment