我有一个非常令人困惑的问题。这是:
[12] pry(EstimatedTime)> EstimatedTime.where(user_id: User.current.id, plan_on: date).pluck(:hours) => []
[13] pry(EstimatedTime)> EstimatedTime.where(user_id: User.current.id, plan_on: date).sum(:hours) => 3.0
这是什么样的魔法?
此语句驻留在从视图中调用的模型方法中。在此之前,在控制器操作中,我正在调用同一模型的另一种方法,即在事务中执行批量创建记录。
def self.save_all(records)
transaction do
records.each do |record|
record.save!
end
end
rescue ActiveRecord::RecordInvalid
return false
end
抛出异常,方法返回false,呈现视图并发生这种情况。
UPD
我找到了一种解决方法,将.sum
替换为.pluck(:hours).sum
,但我仍然不知道为什么我的第一种方法失败。
答案 0 :(得分:0)
正如David Aldrige在对问题的评论中指出的那样,问题是.sum(:hours)
正在使用缓存数据,而.pluck(:hours)
实际上是在查看数据库。
为什么数据库和查询缓存包含不同的数据?好吧,好像在Rails 3中(我应该在提问时指定我的rails版本)失败的事务会回滚数据库,但保持查询缓存完好无损。这导致数据库和缓存之间的临时数据不一致。如this问题所述,在Rails 4中已对此进行了更正。
解决方案1 也就是我为自己选择的那个
事务失败后清除查询缓存。因此,在事务中执行批量插入的方法现在看起来像这样:
def self.save_all(records)
transaction do
records.each do |record|
record.save!
end
end
rescue ActiveRecord::RecordInvalid
self.connection.clear_query_cache
return false
end
解决方案2
我个人认为这不那么优雅,虽然我无法在性能方面比较这些解决方案,所以我会发布它们。人们可以简单地写下这样的sum语句:
EstimatedTime.where(user_id: User.current.id, plan_on: date).pluck(:hours).sum
它将使用数据库数据来计算总和,从而绕过不一致的缓存问题。