Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Updates reset_counters to allow counter name in params

Add support for counter name to be passed as parameter
on `CounterCache::ClassMethods#reset_counters`. This is
to be consistent with the other methods in the module
that all accept counter name.
  • Loading branch information...
commit fec7bfe8d13b7f5a076011364cf68e6ae56f03ff 1 parent ada8e50
@jnormore jnormore authored
View
4 activerecord/CHANGELOG.md
@@ -1,3 +1,7 @@
+* Add support for counter name to be passed as parameter on `CounterCache::ClassMethods#reset_counters`.
+
+ *jnormore*
+
* Restrict deletion of record when using `delete_all` with `uniq`, `group`, `having`
or `offset`.
View
15 activerecord/lib/active_record/counter_cache.rb
@@ -11,7 +11,7 @@ module ClassMethods
# ==== Parameters
#
# * +id+ - The id of the object you wish to reset a counter on.
- # * +counters+ - One or more association counters to reset
+ # * +counters+ - One or more association counters to reset. Association name or counter name can be given.
#
# ==== Examples
#
@@ -19,9 +19,14 @@ module ClassMethods
# Post.reset_counters(1, :comments)
def reset_counters(id, *counters)
object = find(id)
- counters.each do |association|
- has_many_association = reflect_on_association(association.to_sym)
- raise ArgumentError, "'#{self.name}' has no association called '#{association}'" unless has_many_association
+ counters.each do |counter_association|
+ has_many_association = reflect_on_association(counter_association.to_sym)
+ unless has_many_association
+ has_many = reflect_on_all_associations(:has_many)
+ has_many_association = has_many.find { |association| association.counter_cache_column && association.counter_cache_column.to_sym == counter_association.to_sym }
+ counter_association = has_many_association.plural_name if has_many_association
+ end
+ raise ArgumentError, "'#{self.name}' has no association called '#{counter_association}'" unless has_many_association
if has_many_association.is_a? ActiveRecord::Reflection::ThroughReflection
has_many_association = has_many_association.through_reflection
@@ -34,7 +39,7 @@ def reset_counters(id, *counters)
counter_name = reflection.counter_cache_column
stmt = unscoped.where(arel_table[primary_key].eq(object.id)).arel.compile_update({
- arel_table[counter_name] => object.send(association).count
+ arel_table[counter_name] => object.send(counter_association).count
}, primary_key)
connection.update stmt
end
View
16 activerecord/test/cases/counter_cache_test.rb
@@ -51,6 +51,16 @@ class ::SpecialReply < ::Reply
end
end
+ test "reset counters by counter name" do
+ # throw the count off by 1
+ Topic.increment_counter(:replies_count, @topic.id)
+
+ # check that it gets reset
+ assert_difference '@topic.reload.replies_count', -1 do
+ Topic.reset_counters(@topic.id, :replies_count)
+ end
+ end
+
test 'reset multiple counters' do
Topic.update_counters @topic.id, replies_count: 1, unique_replies_count: 1
assert_difference ['@topic.reload.replies_count', '@topic.reload.unique_replies_count'], -1 do
@@ -154,10 +164,10 @@ class ::SpecialReply < ::Reply
end
end
- test "the passed symbol needs to be an association name" do
+ test "the passed symbol needs to be an association name or counter name" do
e = assert_raises(ArgumentError) do
- Topic.reset_counters(@topic.id, :replies_count)
+ Topic.reset_counters(@topic.id, :undefined_count)
end
- assert_equal "'Topic' has no association called 'replies_count'", e.message
+ assert_equal "'Topic' has no association called 'undefined_count'", e.message
end
end
Please sign in to comment.
Something went wrong with that request. Please try again.