Project

General

Profile

« Previous | Next » 

Revision 565dc8e5

Added by Tomer Brisker over 8 years ago

Fixes #12241 - Correct counter_cache deadlock fix

Previous fix had a bug - in `:after_commit` `self.changes` is empty, and the
changes are in `self.previous_changes`. Also this only needs to run on
update.
This commit adds tests to make sure cached_counters continue to work
correctly in the future.

View differences:

app/models/concerns/counter_cache_fix.rb
extend ActiveSupport::Concern
included do
after_commit :update_counter_caches
after_commit :update_counter_caches, :on => :update
def update_counter_caches
self.changes.each do |key, (old_value, new_value)|
self.previous_changes.each do |key, (old_value, new_value)|
if key =~ /_id/
association = self.association(key.sub(/_id$/, '').to_sym)
if association.options[ :counter_cache ]
bundler.d/test.rb
gem 'rubocop-checkstyle_formatter', '~> 0.1'
gem "poltergeist"
gem 'test-unit' if RUBY_VERSION >= '2.2'
gem 'test_after_commit', '~> 0.4'
end
test/unit/concerns/counter_cache_test.rb
require 'test_helper'
# this test uses host and architecture to test that cached counters work as
# expected, this applies to all relations with counter_cache set.
class CounterCacheTest < ActiveSupport::TestCase
setup do
@host = FactoryGirl.create(:host)
@architecture = FactoryGirl.create(:architecture)
end
test 'hosts_count should be 0 for new architecture' do
assert_equal 0, @architecture.hosts_count
end
test 'assigning host to architecture updates count' do
assert_difference "@architecture.hosts_count" do
@architecture.hosts << @host
@architecture.save!
@architecture.reload
end
end
test 'assigning architecture to host updates count' do
assert_difference "@architecture.hosts_count" do
@host.architecture = @architecture
@host.save!
@architecture.reload
end
end
test 'removing architecture from host updates count' do
@host.architecture = @architecture
@host.save!
@architecture.reload
assert_equal 1, @architecture.hosts_count
assert_difference "@architecture.hosts_count", -1 do
@host.architecture = nil
@host.save!
@architecture.reload
end
end
test 'setting architecture_id on host updates count' do
assert_difference "@architecture.hosts_count" do
@host.update_attribute(:architecture_id, @architecture.id)
@architecture.reload
end
end
test 'moving host from one architecture to another should update both counters' do
@architecture2 = FactoryGirl.create(:architecture)
@host.architecture = @architecture
@host.save!
@architecture.reload
assert_equal 1, @architecture.hosts_count
assert_equal 0, @architecture2.hosts_count
@host.architecture = @architecture2
@host.save!
@architecture.reload
@architecture2.reload
assert_equal 0, @architecture.hosts_count
assert_equal 1, @architecture2.hosts_count
end
test 'moving host from one architecture to another by id should update both counters' do
@architecture2 = FactoryGirl.create(:architecture)
@host.architecture = @architecture
@host.save!
@architecture.reload
assert_equal 1, @architecture.hosts_count
assert_equal 0, @architecture2.hosts_count
@host.update_attribute(:architecture_id, @architecture2.id)
@architecture.reload
@architecture2.reload
assert_equal 0, @architecture.hosts_count
assert_equal 1, @architecture2.hosts_count
end
test 'destroying a host updates count' do
@host.architecture = @architecture
@host.save!
@architecture.reload
assert_difference "@architecture.hosts_count", -1 do
@host.destroy
@architecture.reload
end
end
end

Also available in: Unified diff