我的版本是:
我的环境是:
当我写:
Rails.cache.fetch(key) do
User.where('status = 1').limit(1000)
end
无法缓存用户模型。如果我使用
Rails.cache.fetch(key) do
User.all
end
它可以被缓存。如何缓存查询结果?
答案 0 :(得分:32)
原因是因为
User.where('status = 1').limit(1000)
返回ActiveRecord::Relation
,它实际上是范围,而不是查询。 Rails缓存了范围。
如果要缓存查询,则需要在最后使用查询方法,例如#all
。
Rails.cache.fetch(key) do
User.where('status = 1').limit(1000).all
end
请注意缓存ActiveRecord对象永远不是一个好主意。缓存对象可能会导致状态和值不一致。在适用的情况下,应始终缓存基本对象。在这种情况下,请考虑缓存ID。
ids = Rails.cache.fetch(key) do
User.where('status = 1').limit(1000).pluck(:id)
end
User.find(ids)
您可能会争辩说,在这种情况下,对User.find
的调用始终会执行。这是真的,但使用主键的查询速度很快,你可以解决我之前描述的问题。此外,缓存活动记录对象可能很昂贵,并且您可能很快就会用一个缓存条目填充所有Memcached内存。缓存ID也可以防止此问题。
答案 1 :(得分:3)
除了选定的答案:对于Rails 4+,您应该使用load
代替all
来获取范围的结果。
答案 2 :(得分:2)
Rails.cache.fetch
正好缓存了块计算的内容。
User.where('status = 1').limit(1000)
只是一个范围,所以缓存的只是ActiveRecord :: Relation对象,即查询,而不是其结果(因为查询尚未执行)。
如果你想要一些有用的东西被缓存,你需要强制执行块内的查询,例如通过
User.where('status = 1').limit(1000).all
请注意,在导轨4上,all
不会强制加载关系 - 请改用<{1}}
答案 3 :(得分:0)
使用
User.where("status = 1").limit(1000).all
应该有用。