Rails counter_cache not updating correctly

前端 未结 5 681
佛祖请我去吃肉
佛祖请我去吃肉 2021-02-04 00:00

Using Rails 3.1.3 and I\'m trying to figure out why our counter caches aren\'t being updated correctly when changing the parent record id via update_attributes.

         


        
5条回答
  •  孤独总比滥情好
    2021-02-04 00:53

    I recently came across this same problem (Rails 3.2.3). Looks like it has yet to be fixed, so I had to go ahead and make a fix. Below is how I amended ActiveRecord::Base and utilize after_update callback to keep my counter_caches in sync.

    Extend ActiveRecord::Base

    Create a new file lib/fix_counters_update.rb with the following:

    module FixUpdateCounters
    
      def fix_updated_counters
        self.changes.each {|key, value|
          # key should match /master_files_id/ or /bibls_id/
          # value should be an array ['old value', 'new value']
          if key =~ /_id/
            changed_class = key.sub(/_id/, '')
            changed_class.camelcase.constantize.decrement_counter(:"#{self.class.name.underscore.pluralize}_count", value[0]) unless value[0] == nil
            changed_class.camelcase.constantize.increment_counter(:"#{self.class.name.underscore.pluralize}_count", value[1]) unless value[1] == nil
          end
        }
      end 
    end
    
    ActiveRecord::Base.send(:include, FixUpdateCounters)
    

    The above code uses the ActiveModel::Dirty method changes which returns a hash containing the attribute changed and an array of both the old value and new value. By testing the attribute to see if it is a relationship (i.e. ends with /_id/), you can conditionally determine whether decrement_counter and/or increment_counter need be run. It is essnetial to test for the presence of nil in the array, otherwise errors will result.

    Add to Initializers

    Create a new file config/initializers/active_record_extensions.rb with the following:

    require 'fix_update_counters'

    Add to models

    For each model you want the counter caches updated add the callback:

    class Comment < ActiveRecord::Base
      after_update :fix_updated_counters
      ....
    end
    

提交回复
热议问题