ActiveRecord:在计算中将nil视为0?

时间:2017-04-21 00:15:36

标签: ruby-on-rails ruby activerecord null average

我在我的控制器中使用此代码来访问paper_weight分类中所有用户的平均Heavy

if User.where(industry_type: 'Heavy')
 .joins(:papers)
 .where(papers: { paper_type: 'Officepaper' } )
 .pluck('avg(paper_weight)').first.nil?
 @heavy_indust_officepaper == 0
else
@heavy_indust_officepaper = User.where(industry_type: 'Heavy')
 .joins(:papers)
 .where(papers: { paper_type: 'Officepaper' } )
 .pluck('avg(paper_weight)').first * 3 
end

然后变量@heavy_indust_officepaper显示在视图中。

问题是,当一个或多个用户在nil中有paper_type: 'Officepaper'条目时,上面的代码似乎无法正确计算平均值。

我知道因为industry_type: 'Heavy'中有两个用户 其中一个有paper_type: 'Officepaper'的一个条目,即小数30。 其他用户在nil中有paper_type: 'Officepaper'条目。

根据我的理解,计算应为30 + 0 / 2(users) = 15

然后15乘以3,这应该给45

但相反,变量@heavy_indust_officepaper在视图中显示90 ...必须是30 * 3

的结果

有没有办法在上面的代码中将nil转换为0 ???

请有人建议我吗?

以下是我今天早些时候提出的问题的链接,我从中获得了此代码的帮助Using .average with .pluck in ruby on rails app?

2 个答案:

答案 0 :(得分:3)

这里的问题是(除其他外)是你对"hosts": ["tcp://0.0.0.0:2375"] 所做的事情的误解。它为每个用户返回一个平均 someting 的数组。所以在你的例子中它返回

pluck

这就是为什么你得到[30, nil] 90 => [30, nil].first * 30)。

要获得所有用户的平均值,请使用average

解决方案:

在计算平均值时,您可以使用90COALESCE转换为零:

NULL

需要注意的一点是,虽然User.where(industry_type: 'Heavy') .joins(:papers) .where(papers: { paper_type: ['Officepaper', nil] } ) .average('COALESCE(papers.paper_weight, 0)') * 3 #=> 15 会在计算时将任何COALESCE值转换为null,但0仍然会返回average 没有记录来计算nil

如何处理这种情况是由你决定的,但 @max 已经显示了一个非常简单的选项(假设上面的查询结果被写入average变量):

average

答案 1 :(得分:1)

avg = User.where(industry_type: 'Heavy')
 .joins(:papers)
 .where(papers: { paper_type: ['Officepaper', nil] } )
 .average('papers.paper_weight')

@heavy_indust_officepaper = avg.nil? ? 0 : avg * 3