Skip to content

Commit

Permalink
move Rails 4.2 counter cached associations destroy inside callbacks
Browse files Browse the repository at this point in the history
This will allow to detect counter cached columns changes in callbacks
like `after_destroy` or `after_commit on: :destroy`.
  • Loading branch information
sergey-alekseev committed Dec 14, 2014
1 parent 4890ffa commit df67172
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 13 deletions.
23 changes: 10 additions & 13 deletions lib/paranoia.rb
Original file line number Diff line number Diff line change
Expand Up @@ -66,24 +66,21 @@ def self.extended(klazz)
def destroy
callbacks_result = transaction do
run_callbacks(:destroy) do
touch_paranoia_column
end
end
if callbacks_result
if ActiveRecord::VERSION::STRING >= '4.2'
each_counter_cached_associations do |association|
foreign_key = association.reflection.foreign_key.to_sym
unless destroyed_by_association && destroyed_by_association.foreign_key.to_sym == foreign_key
if send(association.reflection.name)
association.decrement_counters
result = touch_paranoia_column
if result && ActiveRecord::VERSION::STRING >= '4.2'
each_counter_cached_associations do |association|
foreign_key = association.reflection.foreign_key.to_sym
unless destroyed_by_association && destroyed_by_association.foreign_key.to_sym == foreign_key
if send(association.reflection.name)
association.decrement_counters
end
end
end
end
result
end
self
else
false
end
callbacks_result ? self : false
end

# As of Rails 4.1.0 +destroy!+ will no longer remove the record from the db
Expand Down
42 changes: 42 additions & 0 deletions test/paranoia_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -672,6 +672,19 @@ def test_counter_cache_column_update_on_destroy#_and_restore_and_really_destroy
# assert_equal 0, parent_model_with_counter_cache_column.reload.related_models_count
end

def test_callbacks_for_counter_cache_column_update_on_destroy
parent_model_with_counter_cache_column = ParentModelWithCounterCacheColumn.create
related_model = parent_model_with_counter_cache_column.related_models.create

assert_equal nil, related_model.instance_variable_get(:@after_destroy_callback_called)
assert_equal nil, related_model.instance_variable_get(:@after_commit_on_destroy_callback_called)

related_model.destroy

assert related_model.instance_variable_get(:@after_destroy_callback_called)
assert related_model.instance_variable_get(:@after_commit_on_destroy_callback_called)
end

# TODO: find a fix for Rails 4.1
if ActiveRecord::VERSION::STRING !~ /\A4\.1/
def test_counter_cache_column_update_on_really_destroy
Expand All @@ -684,6 +697,22 @@ def test_counter_cache_column_update_on_really_destroy
end
end

# TODO: find a fix for Rails 4.0 and 4.1
if ActiveRecord::VERSION::STRING >= '4.2'
def test_callbacks_for_counter_cache_column_update_on_really_destroy!
parent_model_with_counter_cache_column = ParentModelWithCounterCacheColumn.create
related_model = parent_model_with_counter_cache_column.related_models.create

assert_equal nil, related_model.instance_variable_get(:@after_destroy_callback_called)
assert_equal nil, related_model.instance_variable_get(:@after_commit_on_destroy_callback_called)

related_model.really_destroy!

assert related_model.instance_variable_get(:@after_destroy_callback_called)
assert related_model.instance_variable_get(:@after_commit_on_destroy_callback_called)
end
end

private
def get_featureful_model
FeaturefulModel.new(:name => "not empty")
Expand Down Expand Up @@ -746,6 +775,19 @@ class RelatedModel < ActiveRecord::Base
acts_as_paranoid
belongs_to :parent_model
belongs_to :parent_model_with_counter_cache_column, counter_cache: true

after_destroy do |model|
if parent_model_with_counter_cache_column && parent_model_with_counter_cache_column.reload.related_models_count == 0
model.instance_variable_set :@after_destroy_callback_called, true
end
end
after_commit :set_after_commit_on_destroy_callback_called, on: :destroy

def set_after_commit_on_destroy_callback_called
if parent_model_with_counter_cache_column && parent_model_with_counter_cache_column.reload.related_models_count == 0
self.instance_variable_set :@after_commit_on_destroy_callback_called, true
end
end
end

class Employer < ActiveRecord::Base
Expand Down

0 comments on commit df67172

Please sign in to comment.