如何在一行中迭代一个 ActiveRecord 结果集,并且没有检查 Ruby
How to iterate over an ActiveRecord resultset in one line with nil check in Ruby
我有一个 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
有没有一种优雅的方法可以在一行中做同样的事情?
类似这些吗?
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
其中任何一个都应该有效
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
您可以结合安全导航(“隐藏”nil
检查)、数据库内求和(避免从数据库中提取一堆您不需要的数据),以及#to_f
隐藏最终 nil
检查的调用:
cost_rec&.sum(:cost).to_f
如果 cost
是整数,则:
cost_rec&.sum(:cost).to_i
如果 cost
是数据库中的 numeric
并且您不想担心精度问题:
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
来忽略nil
s(因为Array(nil)
是[]
)并且忽略数组和ActiveRecord关系之间的区别(因为#Array
调用 #to_ary
并且关系响应)并说:
Array(cost_rec).sum(&:cost)
这甚至允许 cost_rec
成为单个模型实例。这也绕过了对最终 #to_X
调用的需要,因为 [].sum
是 0
。这种方法的缺点是当 cost_rec
是一个关系时,您不能将求和推入数据库。
当 cost_rec
是 ActiveRecord::Relatation
时,这应该是开箱即用的:
cost_rec.sum(:cost)
我有一个 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
有没有一种优雅的方法可以在一行中做同样的事情?
类似这些吗?
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
其中任何一个都应该有效
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
您可以结合安全导航(“隐藏”nil
检查)、数据库内求和(避免从数据库中提取一堆您不需要的数据),以及#to_f
隐藏最终 nil
检查的调用:
cost_rec&.sum(:cost).to_f
如果 cost
是整数,则:
cost_rec&.sum(:cost).to_i
如果 cost
是数据库中的 numeric
并且您不想担心精度问题:
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
来忽略nil
s(因为Array(nil)
是[]
)并且忽略数组和ActiveRecord关系之间的区别(因为#Array
调用 #to_ary
并且关系响应)并说:
Array(cost_rec).sum(&:cost)
这甚至允许 cost_rec
成为单个模型实例。这也绕过了对最终 #to_X
调用的需要,因为 [].sum
是 0
。这种方法的缺点是当 cost_rec
是一个关系时,您不能将求和推入数据库。
当 cost_rec
是 ActiveRecord::Relatation
时,这应该是开箱即用的:
cost_rec.sum(:cost)