From 53922a08546d5f33878bc8232368dfd21d7a9fb5 Mon Sep 17 00:00:00 2001 From: Gabe da Silveira Date: Wed, 2 Dec 2009 15:28:54 -0800 Subject: [PATCH] Replace reset_counter_cache with reset_counters that has API inline with existing update_counters method --- activerecord/lib/active_record/base.rb | 48 ++++++++++++++++++-------------- activerecord/test/cases/base_test.rb | 4 +- 2 files changed, 29 insertions(+), 23 deletions(-) diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index 7ee2694..57ffe7a 100755 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -389,7 +389,7 @@ module ActiveRecord #:nodoc: # So it's possible to assign a logger to the class through Base.logger= which will then be used by all # instances in the current object space. class Base - ## + ## # :singleton-method: # Accepts a logger conforming to the interface of Log4r or the default Ruby 1.8+ Logger class, which is then passed # on to any new database connections made and which can be retrieved on both a class and instance level by calling +logger+. @@ -423,11 +423,11 @@ module ActiveRecord #:nodoc: # as a Hash. # # For example, the following database.yml... - # + # # development: # adapter: sqlite3 # database: db/development.sqlite3 - # + # # production: # adapter: sqlite3 # database: db/production.sqlite3 @@ -916,24 +916,30 @@ module ActiveRecord #:nodoc: connection.select_value(sql, "#{name} Count").to_i end - # Reset a counter cache for all records. + # Resets one or more counter caches to their correct value using an SQL + # count query. This is useful when adding new counter caches, or if the + # counter has been corrupted or modified directly by SQL. # # ==== Parameters # - # * +association_name+ - The name of of the association counter cache to reset + # * +id+ - The id of the object you wish to reset a counter on. + # * +counters+ - One or more counter names to reset # # ==== Examples - # # For all Post records reset the comments_count - # Post.reset_counter_cache(:comments) - def reset_counter_cache(association) - child_class = reflect_on_association(association).klass - counter_name = child_class.reflect_on_association(self.name.downcase.to_sym).counter_cache_column + # + # # For Post with id #1 records reset the comments_count + # Post.reset_counters(1, :comments) + 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 - find_each do |object| connection.update("UPDATE #{quoted_table_name} SET #{connection.quote_column_name(counter_name)} = #{object.send(association).count} WHERE #{connection.quote_column_name(primary_key)} = #{quote_value(object.id)}", "#{name} UPDATE") end end + # A generic "counter updater" implementation, intended primarily to be # used by increment_counter and decrement_counter, but which may also # be useful on its own. It simply does a direct SQL update for the record @@ -1360,7 +1366,7 @@ module ActiveRecord #:nodoc: def self_and_descendants_from_active_record#nodoc: klass = self classes = [klass] - while klass != klass.base_class + while klass != klass.base_class classes << klass = klass.superclass end classes @@ -1394,7 +1400,7 @@ module ActiveRecord #:nodoc: def human_name(options = {}) defaults = self_and_descendants_from_active_record.map do |klass| :"#{klass.name.underscore}" - end + end defaults << self.name.humanize I18n.translate(defaults.shift, {:scope => [:activerecord, :models], :count => 1, :default => defaults}.merge(options)) end @@ -1967,7 +1973,7 @@ module ActiveRecord #:nodoc: attributes = construct_attributes_from_arguments( # attributes = construct_attributes_from_arguments( [:#{attribute_names.join(',:')}], args # [:user_name, :password], args ) # ) - # + # scoped(:conditions => attributes) # scoped(:conditions => attributes) end # end }, __FILE__, __LINE__ @@ -2491,7 +2497,7 @@ module ActiveRecord #:nodoc: # name # end # end - # + # # user = User.find_by_name('Phusion') # user_path(user) # => "/users/Phusion" def to_param @@ -2546,12 +2552,12 @@ module ActiveRecord #:nodoc: # If +perform_validation+ is true validations run. If any of them fail # the action is cancelled and +save+ returns +false+. If the flag is # false validations are bypassed altogether. See - # ActiveRecord::Validations for more information. + # ActiveRecord::Validations for more information. # # There's a series of callbacks associated with +save+. If any of the # before_* callbacks return +false+ the action is cancelled and # +save+ returns +false+. See ActiveRecord::Callbacks for further - # details. + # details. def save create_or_update end @@ -2563,12 +2569,12 @@ module ActiveRecord #:nodoc: # # With save! validations always run. If any of them fail # ActiveRecord::RecordInvalid gets raised. See ActiveRecord::Validations - # for more information. + # for more information. # # There's a series of callbacks associated with save!. If any of # the before_* callbacks return +false+ the action is cancelled # and save! raises ActiveRecord::RecordNotSaved. See - # ActiveRecord::Callbacks for further details. + # ActiveRecord::Callbacks for further details. def save! create_or_update || raise(RecordNotSaved) end @@ -2741,12 +2747,12 @@ module ActiveRecord #:nodoc: # class User < ActiveRecord::Base # attr_protected :is_admin # end - # + # # user = User.new # user.attributes = { :username => 'Phusion', :is_admin => true } # user.username # => "Phusion" # user.is_admin? # => false - # + # # user.send(:attributes=, { :username => 'Phusion', :is_admin => true }, false) # user.is_admin? # => true def attributes=(new_attributes, guard_protected_attributes = true) diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb index 5a4b190..e1579b0 100755 --- a/activerecord/test/cases/base_test.rb +++ b/activerecord/test/cases/base_test.rb @@ -627,13 +627,13 @@ class BasicsTest < ActiveRecord::TestCase assert_equal -2, Topic.find(2).replies_count end - def test_reset_counter_cache + def test_reset_counters assert_equal 1, Topic.find(1).replies_count Topic.increment_counter("replies_count", 1) assert_equal 2, Topic.find(1).replies_count - Topic.reset_counter_cache(:replies) + Topic.reset_counters(1, :replies) assert_equal 1, Topic.find(1).replies_count end -- 1.6.0.2