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.
From the fine manual:
:counter_cache
Caches the number of belonging objects on the associate class through the use of
increment_counter
anddecrement_counter
. The counter cache is incremented when an object of this class is created and decremented when it’s destroyed.
There's no mention of updating the cache when an object is moved from one owner to another. Of course, the Rails documentation is often incomplete so we'll have to look at the source for confirmation. When you say :counter_cache => true
, you trigger a call to the private add_counter_cache_callbacks method and add_counter_cache_callbacks does this:
after_create
callback which calls increment_counter.before_destroy
callback which calls decrement_counter.I don't think you're expecting too much, you're just expecting ActiveRecord to be more complete than it is.
All is not lost though, you can fill in the missing pieces yourself without too much effort. If you want to allow reparenting and have your counters updated, you can add a before_save
callback to your ExhibitorRegistration that adjusts the counters itself, something like this (untested demo code):
class ExhibitorRegistration < ActiveRecord::Base
belongs_to :event, :counter_cache => true
before_save :fix_counter_cache, :if => ->(er) { !er.new_record? && er.event_id_changed? }
private
def fix_counter_cache
Event.decrement_counter(:exhibitor_registration_count, self.event_id_was)
Event.increment_counter(:exhibitor_registration_count, self.event_id)
end
end
If you were adventurous, you could patch something like that into ActiveRecord::Associations::Builder#add_counter_cache_callbacks
and submit a patch. The behavior you're expecting is reasonable and I think it would make sense for ActiveRecord to support it.