Why is counter_cache column not increasing when << an



假设我有以下模型:

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

我真的被计数器_缓存半工作弄糊涂了。我也找不到配置问题。

在本项目中使用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这样的东西是不合适的。

通过写这篇文章,发生了两件事:

  1. Storable.create使用location_id nil 创建新的可存储对象

  2. l.storables <<更新创建的对象,将location_id设置为l.id,并且不知何故忘记更新计数器缓存。

这可能是ActiveRecord的错,因为它本应该更智能,但实际上您已经执行了两个SQL(insert into storable&update storable set location_id=something),只是为了插入一个新的可存储记录。无论如何,这是个坏主意,如果您对location_id有外键约束,第一次插入甚至会失败。

所以用l.storables << Storable.new代替

PS:对于l.storables << Storable.create,由于Storable.create的返回值不是新记录,所以l很难决定该怎么做。在某些情况下,它需要增加自己的计数器缓存,在其他情况下,需要增加自己计数器缓存并减少其他人的计算器缓存,或者它可能什么都不需要。

最新更新