当返回0时,Sum返回值

时间:2015-06-17 14:48:03

标签: ruby-on-rails ruby-on-rails-3

我有一个非常令人困惑的问题。这是:

[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,但我仍然不知道为什么我的第一种方法失败。

1 个答案:

答案 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

它将使用数据库数据来计算总和,从而绕过不一致的缓存问题。