0

我有一个 Active Record 结果数组,我想遍历每条记录以获取特定属性并将所有这些属性添加到一行中并进行 nil 检查。这是我到目前为止得到的

def total_cost(cost_rec)
    total= 0.0
    unless cost_rec.nil?
      cost_rec.each { |c| total += c.cost }
    end
    total
  end

有没有一种优雅的方法可以在一行中做同样的事情?

4

4 回答 4

1

像这些吗?

def total_cost(cost_rec)
  (cost_rec || []).inject(0) { |memo, c| memo + c.cost }
end

或者

def total_cost(cost_rec)
  (cost_rec || []).sum(&:cost)
end
于 2021-01-12T22:01:35.027 回答
1

这些中的任何一个都应该工作

total = cost_rec.map(&:cost).compact.sum
total = cost_rec.map{|c| c.cost }.compact.sum
total = cost_rec.pluck(:cost).compact.sum

编辑:如果 cost_rec 为零

total = (cost_rec || []).map{|c| c.cost }.compact.sum
于 2021-01-12T22:19:18.800 回答
1

您可以结合安全导航(“隐藏”nil检查)、数据库内的求和(以避免从数据库中提取一堆不需要的数据)以及隐藏最终检查的#to_f调用:nil

cost_rec&.sum(:cost).to_f

如果cost是整数,则:

cost_rec&.sum(:cost).to_i

并且 ifcostnumeric数据库内部的并且您不想担心精度问题:

cost_rec&.sum(:cost).to_d

如果cost_rec是一个数组而不是一个关系(即您已经从数据库中提取了所有数据),那么其中之一:

cost_rec&.sum(&:cost).to_f
cost_rec&.sum(&:cost).to_i
cost_rec&.sum(&:cost).to_d

取决于是什么类型cost

您还可以使用Kernel#Array忽略nils (因为Array(nil)is [])并忽略数组和 ActiveRecord 关系之间的区别(因为#Array调用#to_ary和关系对此作出响应)并说:

Array(cost_rec).sum(&:cost)

这甚至允许cost_rec成为单个模型实例。这也绕过了对最终#to_X调用的需要,因为[].sumis 0。这种方法的缺点是您不能在cost_rec关系中将总和推送到数据库中。

于 2021-01-12T22:53:59.290 回答
0

什么时候cost_recActiveRecord::Relatation然后这应该开箱即用:

cost_rec.sum(:cost)

ActiveRecord::Calculations#sum

于 2021-01-13T05:56:39.510 回答