From bc84bd17d1f981ca4899f336f6b94e552bc6a058 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mislav=20Marohni=C4=87?= Date: Sat, 17 Apr 2010 02:01:38 +0200 Subject: fix `reset_counters` to work even with complex class names e.g. it guesses that a belongs_to association to Namespace::MyModel is named "my_model", unlike before where it would look up an association named "namespace::mymodel" and fail. --- activerecord/lib/active_record/counter_cache.rb | 10 ++++++---- activerecord/test/cases/counter_cache_test.rb | 25 +++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/activerecord/lib/active_record/counter_cache.rb b/activerecord/lib/active_record/counter_cache.rb index 3bdb6970f8..9601ed6afd 100644 --- a/activerecord/lib/active_record/counter_cache.rb +++ b/activerecord/lib/active_record/counter_cache.rb @@ -16,13 +16,15 @@ module ActiveRecord def reset_counters(id, *counters) object = find(id) counters.each do |association| - child_class = reflect_on_association(association).klass - counter_name = child_class.reflect_on_association(self.name.downcase.to_sym).counter_cache_column + child_class = reflect_on_association(association.to_sym).klass + belongs_name = self.name.demodulize.underscore.to_sym + counter_name = child_class.reflect_on_association(belongs_name).counter_cache_column - self.unscoped.where(arel_table[self.primary_key].eq(object.id)).arel.update( + self.unscoped.where(arel_table[self.primary_key].eq(object.id)).arel.update({ arel_table[counter_name] => object.send(association).count - ) + }) end + return true end # A generic "counter updater" implementation, intended primarily to be diff --git a/activerecord/test/cases/counter_cache_test.rb b/activerecord/test/cases/counter_cache_test.rb index b72356cf6f..377de168b9 100755 --- a/activerecord/test/cases/counter_cache_test.rb +++ b/activerecord/test/cases/counter_cache_test.rb @@ -7,6 +7,14 @@ require 'models/categorization' class CounterCacheTest < ActiveRecord::TestCase fixtures :topics, :categories, :categorizations + class SpecialTopic < ::Topic + has_many :special_replies, :foreign_key => 'parent_id' + end + + class SpecialReply < ::Reply + belongs_to :special_topic, :foreign_key => 'parent_id', :counter_cache => 'replies_count' + end + setup do @topic = Topic.find(1) end @@ -32,6 +40,23 @@ class CounterCacheTest < ActiveRecord::TestCase Topic.reset_counters(@topic.id, :replies) end end + + test "reset counters with string argument" do + Topic.increment_counter('replies_count', @topic.id) + + assert_difference '@topic.reload.replies_count', -1 do + Topic.reset_counters(@topic.id, 'replies') + end + end + + test "reset counters with modularized and camelized classnames" do + special = SpecialTopic.create!(:title => 'Special') + SpecialTopic.increment_counter(:replies_count, special.id) + + assert_difference 'special.reload.replies_count', -1 do + SpecialTopic.reset_counters(special.id, :special_replies) + end + end test "update counter with initial null value" do category = categories(:general) -- cgit v1.2.3