假设我有以下模型:
class Location < Active::Record
has_many :storables, foreign_key: :bin_id
# ...
end
class Storable < Active::Record
belongs_to :bin, class_name: :Location, counter_cache: true
# ...
end
当我运行以下规范时,counter_cache
没有正确递增。方法 #1
和 #2
按预期工作,但不是 #3
。给了什么?
describe "location storables" do
specify "adding a storable increments the counter cache" do
l = Location.create
l.storables_count.should == 0 #=> PASSES
# method 1
s = Storable.create(bin: l)
l.reload
l.storables_count.should == 1 #=> PASSES
# method 2
l.storables.create
l.reload
l.storables_count.should == 2 #=> PASSES
# method 3
l.storables << Storable.create
l.reload
l.storables_count.should == 3 #=> FAILS, got 2 not 3
end
end
我真的对counter_cache half working感到困惑。我也找不到配置问题。
在此项目上使用 Rails 3.2.12。
更新
升级到 rails 4 没有帮助。此外,如果我将方法 #3 更改为以下内容,则测试通过:
# method 3
l.storables << Storable.create
puts "proxy : #{l.storables.count}" #=> 3
puts "relation : #{Storable.count}" #=> 3
puts "cache : #{l.storables_count}" #=> 2
Location.reset_counters(l.id, :storables) # corrects cache
l.reload
l.storables_count.should == 3 #=> PASSES
为什么这不是自动发生的?
最佳答案
一方面,我认为写类似l.storables << Storable.create
的东西不合适。 .
通过编写此代码,会发生两件事:
Storable.create
使用location_id
创建一个新的 Storable 对象无l.storables <<
更新创建的对象,将 location_id 设置为l.id
,并以某种方式忘记更新计数器缓存。
这可能是 ActiveRecord 的错,因为它应该更聪明,但您实际上执行了两个 SQL(insert into storable & update storable set location_id = something)只是为了插入一个新的可存储记录。无论如何,这是个坏主意,如果你对 location_id 有外键约束,第一次插入甚至会失败。
所以使用l.storables << Storable.new
相反
附注:与l.storables << Storable.create
, 因为返回值为 Storable.create
不是新记录,有点难l
决定做什么。在某些情况下,它需要增加自己的计数器缓存,在其他情况下,它需要增加自己的计数器缓存并减少其他人的计数器缓存,或者它可能什么都不做。
关于ruby-on-rails - 为什么 << 关联时 counter_cache 列不增加?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17583163/