web-dev-qa-db-ja.com

Rails 4モデルメソッドによる合計

私のアプリには、いくつかの計算を実行するgoal_ytdメソッドを持つUserモデルがあります。

コントローラーには、Userまたはusers@usersの変数ActiveRecord::Relationがあり、@usersgoal_ytdsをすべて合計したいと思います。

私の最初の傾向は:

@users.sum(&:goal_ytd)

ActiveRecord::Relationsumを使用することは、Rails 4.1。

そこで、コードを次のように変更しました。

@users.to_a.sum(&:goal_ytd)

次に、NoMethodErrorをスローしました。これは、特定の状況では、@users@users = Userによって割り当てられ、Userにはto_aメソッドがないためです。

@usersを使用して@users = User.allを割り当てると、Relation#allも非推奨になるため、非推奨の警告がスローされます。

すべてのUsersを配列として取得する方法はありますか?もっと良い方法はありますか?

16
J3RN

オンRails 4.1

goal_ydtがusersテーブルの列の場合:

@users.sum(:goal_ydt)

goal_ydtUserクラスのメソッドの場合:

@users.to_a.sum(&:goal_ydt)
32
dazonic

mapsumの組み合わせを使用するのが好きです

@users.map(&:goal_ydt).sum
4
Fran Martinez

ここでは、列挙可能なメソッドを使用しないでください。 ActiveRecord :: Relationshipで定義され、パラメータとしてシンボルを受け取るsumを使用します。主な違いは、データベースでSUMクエリを実行するため、dbからすべてのレコードをプルするよりもはるかに高速であるということです。また、レコードのいずれかで特定のフィールドの値が空白の場合、列挙可能なsumはエラーをスローしますが、ActiveRecordのエラーはスローしません。要するに:

@users.sum(:goal_ydt)  

編集:

ただし、goal_ydtはフィールドではなくメソッドであり、モデルをループする以外に選択肢はありません。私が通常これを行う方法は、scopedメソッドを使用することです。

@users.scoped.sum(&:goal_ydt)
3
BroiSatse

ここでの問題は、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)

新しい質問は次のようになります。すべてのユーザーの目標を、すべてをメモリにロードせずに、できれば1行で合計するにはどうすればよいですか。それはまた別の日だと思います。

0
J3RN