我有以下三种模型(经过简化):
class A < ActiveRecord::Base
has_many :bs
has_many :cs, :through => :bs
end
class B < ActiveRecord::Base
belongs_to :a
has_many :cs
end
class C < ActiveRecord::Base
belongs_to :b
end
[A.cs似乎在我第一次不想使用时(每个对象)被缓存了。
这是一个突出显示问题的控制台会话(绒毛已被编辑)
rails console
001 > b = B.create
002 > c = C.new
003 > c.b = b
004 > c.save
005 > a = A.create
006 > a.bs << b
007 > a.cs
=> [#<C id: 1, b_id: 1>]
这的确是您所期望的。 a.cs通过a.bs关系进展顺利。
008 > a2 = A.create
009 > a2.cs
=> []
010 > a2.bs << b
011 > a2.cs
=> []
因此,对a2.cs的第一次调用(导致数据库查询)完全正确地没有返回Cs。但是,第二个调用显示出C的明显不足,即使Cs应该存在(没有发生数据库查询)也是如此。
012 > A.find(a2.id).cs
=> [#<C id: 1, b_id: 1>]
同样,执行数据库查询以获取A记录和关联的C。
因此,回到问题所在:如何强制Rails不使用缓存的结果?我当然可以辞职去做这种解决方法(如控制台步骤12所示),但是由于在只需要一个查询的情况下会导致另外两个查询,所以我宁愿不要。
我对此问题进行了更多研究。尽管使用clear_association_cache
非常方便,但是在使缓存无效的每个操作之后添加它都不会感到DRY。我认为Rails应该能够对此进行跟踪。幸运的是,有一种方法!
((编辑:请参见Daniel Waltrip的答案,他远胜于我的)
我发现了另一种禁用查询缓存的方法。在您的模型中,只需添加一个default_scope
所有关联方法都是围绕缓存构建的,它使最新查询的结果可用于进一步的操作。缓存甚至在方法之间共享。例如:
要清除缓存,请使用.reload