我遇到了一个非常令人困惑的问题。在这里:
[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
,但我仍然不知道为什么我的第一种方法失败了。
正如David Aldrige在对该问题的评论中指出的那样,问题在于.sum(:hours)
正在使用缓存的数据,而.pluck(:hours)
实际上是在研究数据库。
为什么数据库和查询缓存包含不同的数据?好吧,似乎在 Rails 3 中(我应该在提问时指定我的 rails 版本)失败的事务会回滚数据库,但保持查询缓存不变。这导致数据库和缓存之间的临时数据不一致。如本期所述,此问题已在 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
它将使用数据库数据来计算总和,绕过不一致的缓存问题。