20

在我的应用程序中,我有一个User带有goal_ytd方法的模型,可以执行一些计算。

在控制器中,我有一个@users可能是User或 的ActiveRecord::Relation变量,users我想对所有的@userss求和goal_ytd

我的第一个倾向是:

@users.sum(&:goal_ytd)

这在这两种情况下都引发了弃用警告,因为在 Rails 4.1 中使用sumon anActiveRecord::Relation正在消失。

因此,我将代码更改为:

@users.to_a.sum(&:goal_ytd)

然后抛出一个NoMethodError,因为在某种情况下,@users被分配@users = User并且User没有to_a方法。

分配@usersusing@users = User.all会引发弃用警告,因为Relation#all也已弃用。

有没有办法把所有的都Users作为一个数组?有没有更好的办法?

4

4 回答 4

44

在 Rails 4.1 上

如果goal_ydt是用户表中的一列:

@users.sum(:goal_ydt)

如果goal_ydtUser类中的方法:

@users.to_a.sum(&:goal_ydt)
于 2014-09-08T09:39:55.680 回答
5

我喜欢结合使用mapsum

@users.map(&:goal_ydt).sum
于 2016-11-22T09:01:31.520 回答
3

您不应该在这里使用可枚举的方法。使用sum在 ActiveRecord::Relation 上定义并将符号作为参数。主要区别在于它将SUM在您的数据库中执行查询,因此它比从数据库中提取所有记录要快得多。此外,如果您的任何记录对于给定字段具有空白值,则 enumerablesum将引发错误,而 ActiveRecord 则不会。简而言之:

@users.sum(:goal_ydt)  

编辑:

但是,由于goal_ydt不是字段而是方法,因此您别无选择,只能遍历模型。我通常这样做的方法是使用scoped方法:

@users.scoped.sum(&:goal_ydt)
于 2014-08-12T22:34:32.407 回答
1

这里的问题源于对Relation#all弃用的根本误解。虽然Relation#all已弃用,Model#all但不是。所以:

@users = User.all

仍然完全有效,同时:

@users = User.where(first_name: "Mike").all

已弃用。

所以最终的解决方案看起来像:

@users = User.all
unless current_user.admin?
  @users = @users.where(company_id: current_user.company_id)
end
@users.to_a.sum(&:goal_ytd)

一个新问题是:我如何总结所有用户的目标,最好在一行中,而不将它们全部加载到内存中?我想那是另一天。

于 2014-08-13T16:46:40.680 回答