Skip to content

Instantly share code, notes, and snippets.

Created September 29, 2011 19:06
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
What would you like to do?
Updates inverse counter caches when #collection_singular_ids= is called for an object extending ActiveRecord::Base
module DistantCounters
extend ActiveSupport::Concern
included do
reflect_on_all_associations.each do |reflection|
next unless reflection.macro == :has_many and reflection.is_a? ActiveRecord::Reflection::ThroughReflection
next unless reflection.klass.column_names.include? "#{name.underscore.pluralize}_count"
assoc_name =
redefine_method "#{assoc_name}_ids=" do |ids|
counter_cache_key = "#{}_count"
new_ids =
old_ids = send "#{assoc_name}_ids"
(old_ids - new_ids).each { |an_id| reflection.klass.decrement_counter counter_cache_key, an_id }
(new_ids - old_ids).each { |an_id| reflection.klass.increment_counter counter_cache_key, an_id }
association(assoc_name.pluralize.to_sym).ids_writer ids
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment