Skip to content

Instantly share code, notes, and snippets.

Embed
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 = reflection.name.to_s.singularize
redefine_method "#{assoc_name}_ids=" do |ids|
counter_cache_key = "#{self.class.name.underscore.pluralize}_count"
new_ids = ids.map(&:to_s).reject(&:empty?).map(&:to_i)
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
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment