Rails counter_cache 未正确更新 [英] Rails counter_cache not updating correctly

查看:48
本文介绍了Rails counter_cache 未正确更新的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用 Rails 3.1.3,我试图弄清楚为什么在通过 update_attributes 更改父记录 ID 时我们的计数器缓存没有被正确更新.

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.

class ExhibitorRegistration < ActiveRecord::Base
  belongs_to :event, :counter_cache => true
end

class Event < ActiveRecord::Base
  has_many :exhibitor_registrations, :dependent => :destroy
end

describe ExhibitorRegistration do
  it 'correctly maintains the counter cache on events' do
    event = Factory(:event)
    other_event = Factory(:event)
    registration = Factory(:exhibitor_registration, :event => event)

    event.reload
    event.exhibitor_registrations_count.should == 1

    registration.update_attributes(:event_id => other_event.id)

    event.reload
    event.exhibitor_registrations_count.should == 0

    other_event.reload
    other_event.exhibitor_registrations_count.should == 1
  end
end

此规范失败,表明事件的计数器缓存未递减.

This spec fails indicating that the counter cache on event is not being decremented.

1) ExhibitorRegistration correctly maintains the counter cache on events
   Failure/Error: event.exhibitor_registrations_count.should == 0
     expected: 0
          got: 1 (using ==)

我是否应该期望这会起作用,还是我需要手动跟踪更改并自己更新计数器?

Should I even expect this to work or do I need to manually track the changes and update the counter myself?

推荐答案

来自 精美手册:

:counter_cache

通过使用increment_counterdecrement_counter 缓存关联类上所属对象的数量.计数器缓存在此类对象创建时递增,销毁时递减.

Caches the number of belonging objects on the associate class through the use of increment_counter and decrement_counter. The counter cache is incremented when an object of this class is created and decremented when it’s destroyed.

当对象从一个所有者移动到另一个所有者时,没有提到更新缓存.当然,Rails 文档通常是不完整的,因此我们必须查看源以进行确认.当你说 :counter_cache =>真的,你#Lreferr="relno触发对私有add_counter_cache_callbacks 方法add_counter_cache_callbacks 这样做:

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:

  1. 添加一个 after_create 回调,它调用 increment_counter.
  2. 添加一个 before_destroy 回调,它调用 decrement_counter.
  3. 调用 attr_readonly 将计数器列设为只读.
  1. Adds an after_create callback which calls increment_counter.
  2. Adds an before_destroy callback which calls decrement_counter.
  3. Calls attr_readonly to make the counter column readonly.

我认为您并没有期望太多,您只是期望 ActiveRecord 比现在更完整.

I don't think you're expecting too much, you're just expecting ActiveRecord to be more complete than it is.

虽然一切都没有丢失,您可以毫不费力地自己填补缺失的部分.如果您想允许重新父级并更新您的计数器,您可以将 before_save 回调添加到您的 ExhibitorRegistration 以调整计数器本身,如下所示(未经测试的演示代码):

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

如果您喜欢冒险,可以将类似的内容修补到 ActiveRecord::Associations::Builder#add_counter_cache_callbacks 中并提交补丁.您期望的行为是合理的,我认为 ActiveRecord 支持它是有意义的.

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.

这篇关于Rails counter_cache 未正确更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆