سؤال

I am using a counter_cache to let MySQL do some of the bookkeeping for me:

class Container
  has_many :items
end

class Item
  belongs_to :container, :counter_cache => true
end

Now, if I do this:

container = Container.find(57)
item = Item.new
item.container = container
item.save

in the SQL log there will be an INSERT followed by something like:

UPDATE `containers` SET `items_count` = COALESCE(`items_count`, 0) + 1
    WHERE `containers`.`id` = 57

which is what I expected it to do. However, the container[:items_count] will be stale!

...unless I container.reload to pick up the updated value. Which in my mind sort of defeats part of the purpose of using the :counter_cache in favor of a custom built one, especially since I may not actually want a reload before I try to access the items_count attribute. (My models are pretty code-heavy because of the nature of the domain logic, so I sometimes have to save and create multiple things in one controller call.)

I understand I can tinker with callbacks myself but this seems to me a fairly basic expectation of the simple feature. Again, if I have to write additional code to make it fully work, it might as well be easier to implement a custom counter.

What am I doing/assuming wrong?

هل كانت مفيدة؟

المحلول 2

You haven't actually made the container aware of the item though, which is effectively what you do when you container.reload! it. Have you tried:

container = Container.find(57)
item = container.items.create()

This will make the item in the context of the container and build those associations for you.

نصائح أخرى

You shouldn't expect the value of the items counter to be automatically updated in your Container instance. Keep in mind that most Rails applications operate in a multiple process (and often multiple server) configuration. If one process adds an Item that is associated with a Container instance on a different process, the value of the counter will become stale.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top