Rails 4 Sum by Model Method

后端 未结 4 1207
夕颜
夕颜 2021-02-13 02:07

In my app, I have a User model, with a goal_ytd method, which performs some calculations.

In a controller, I have a variable @users

相关标签:
4条回答
  • 2021-02-13 02:45

    I like to use a combination of map and sum

    @users.map(&:goal_ydt).sum
    
    0 讨论(0)
  • 2021-02-13 02:48

    On Rails 4.1

    If goal_ydt is a column in the users table:

    @users.sum(:goal_ydt)
    

    If goal_ydt is a method in User class:

    @users.to_a.sum(&:goal_ydt)
    
    0 讨论(0)
  • 2021-02-13 02:59

    The issue here is rooted in a fundamental misunderstanding of the Relation#all deprecation. While Relation#all is deprecated, Model#all is not. Therefore:

    @users = User.all
    

    is still perfectly valid, while:

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

    is deprecated.

    So the end solution looks like:

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

    A new question would be: How do I sum all the users goals, preferably in one line, without loading them all into memory? I suppose that's for another day.

    0 讨论(0)
  • 2021-02-13 03:10

    You should not use enumerable methods here. Use sum which is defined on ActiveRecord::Relation and takes symbol as parameter. The main difference is that it will perform SUM query in your database, so it is much faster than pulling all the records form db. Also if any of your record has blank value for given field, enumerable sum will throw an error, while ActiveRecord's one will not. In short:

    @users.sum(:goal_ydt)  
    

    EDIT:

    However since goal_ydt is not a field but a method, you have no choice but to loop over the models. The way I usually do this is by using scoped method:

    @users.scoped.sum(&:goal_ydt)
    
    0 讨论(0)
提交回复
热议问题