Rails 4按模型方法求和
在我的应用程序中,我有一个User
模型,带有goal_ytd
方法,它执行一些计算。
在一个控制器中,我有一个变量@users
,可能是User
或ActiveRecord::Relation
goal_ytd
的users
,我想总结所有@users
的goal_ytd
。
我的第一个倾向是:
@users.sum(&:goal_ytd)
在两种情况下都抛出了弃用警告,因为在Active 4.1中使用对ActiveRecord::Relation
sum
消失了。
所以,我将代码更改为:
@users.to_a.sum(&:goal_ytd)
然后抛出一个NoMethodError
因为在某种情况下, NoMethodError
由@users = User
分配,而User
没有to_a
方法。
使用@users = User.all
分配@users
会抛出弃用警告,因为Relation#all
也已弃用。
有没有办法让所有Users
成为一个数组? 有没有更好的办法?
在Rails 4.1
如果goal_ydt
是users表中的列:
@users.sum(:goal_ydt)
如果goal_ydt
是User
类中的方法:
@users.to_a.sum(&:goal_ydt)
你不应该在这里使用可枚举的方法。 使用在ActiveRecord :: Relation上定义的sum
,并将symbol作为参数。 主要区别在于它将在您的数据库中执行SUM
查询,因此它比从db中提取所有记录要快得多。 此外,如果您的任何记录对于给定字段具有空值,则可枚举的sum
将抛出错误,而ActiveRecord的则不会。 简而言之:
@users.sum(:goal_ydt)
编辑:
但是由于goal_ydt
不是一个字段而是一个方法,你别无选择,只能遍历模型。 我通常这样做的方法是使用scoped
方法:
@users.scoped.sum(&:goal_ydt)
我喜欢使用map
和sum
的组合
@users.map(&:goal_ydt).sum
这里的问题根源于对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)
一个新的问题是:我如何总结所有用户目标,最好是在一行中,而不是将它们全部加载到内存中? 我想那是另一天。