はじめに
本記事は、 駆け出しエンジニアの第一歩!AdventCalendar2020 13日目の記事です。
Railsで表の合計値を算出するにあたって、aggregate関数なるものが便利でスマートだったので、記事にしてみました。
開発環境
IDE:Cloud9
Ruby:2.6.3
Rails:5.2.4
実例をみてみる
やりたいこと
ER図
aggregate関数を使わない場合
controllers/carts.rb
def new
@carts = Cart.where(user_id: current_user.id)
end
例えば、たんぱく質(protain)の合計値を表示したい場合
views/carts/new.html.rb
<% sum = 0 %>
<% @carts.each do |cart| %>
<% sum += cart.food.protain %>
<% end %>
<%= sum %>
これだと、1つの項目(上記の場合たんぱく質)を表示するのに、5行も必要となってしまい、見ため的にあまりスマートとはいえない。
views/carts/new.html.rb
<td>合計</td>
<td>
<% sum = 0 %>
<% @carts.each do |cart| %>
<% sum += cart.food.calorie %>
<% end %>
<%= sum %>
</td>
<td>
<% sum = 0 %>
<% @carts.each do |cart| %>
<% sum += cart.food.protain %>
<% end %>
<%= sum %>
</td>
<td>
<% sum = 0 %>
<% @carts.each do |cart| %>
<% sum += cart.food.fat %>
<% end %>
<%= sum %>
</td>
<td>
<% sum = 0 %>
<% @carts.each do |cart| %>
<% sum += cart.food.carbon %>
<% end %>
<%= sum %>
</td>
表全体を表示すると、割とfat感がある。
そこでaggregate関数を用いて、もっとスマートに記述する。
aggregate関数を使う方法
コントローラはさっきと一緒。
controllers/carts.rb
def new
@carts = Cart.where(user_id: current_user.id)
end
カートモデルに以下を記述する。
model/cart.rb
def self.aggregate(column)
self.all.map { |cart| cart.food[column] }.sum
end
views/carts/new.html.rb
<td>合計</td>
<td>
<%= @carts.aggregate(:calorie) %>
</td>
<td>
<%= @carts.aggregate(:protain) %>
</td>
<td>
<%= @carts.aggregate(:fat) %>
</td>
<td>
<%= @carts.aggregate(:carbon) %>
</td>
めっちゃすまーと。