gpt4 book ai didi

ruby-on-rails - Rails counter_cache 未正确更新

转载 作者:行者123 更新时间:2023-12-03 11:31:52 26 4
gpt4 key购买 nike

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

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

此规范失败表明事件的计数器缓存未减少。
1) ExhibitorRegistration correctly maintains the counter cache on events
Failure/Error: event.exhibitor_registrations_count.should == 0
expected: 0
got: 1 (using ==)

我什至应该期望它起作用还是我需要手动跟踪更改并自己更新计数器?

最佳答案

来自 fine manual :

:counter_cache

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 => true ,你 trigger a call to the private add_counter_cache_callbacks method add_counter_cache_callbacks does this :
  • 添加 after_create调用 increment_counter 的回调.
  • 添加 before_destroy调用 decrement_counter 的回调.
  • 调用 attr_readonly 使计数器列只读。

  • 我不认为您期望太多,您只是期望 ActiveRecord 比它更完整。

    但是,一切都没有丢失,您可以毫不费力地自己填补缺失的部分。如果您想允许重新 parent 并更新您的计数器,您可以添加 before_save回调到您的 ExhibitorRegistration 来调整计数器本身,就像这样(未经测试的演示代码):
    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 支持它是有意义的。

    关于ruby-on-rails - Rails counter_cache 未正确更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9403577/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com