#はじめに
現在オリジナルアプリ「morning-walk」という朝散歩を習慣化するアプリを制作中です。
その中で、月毎の散歩日数と散歩時間を集計する実装を行ったので、まとめます。
#前提条件
・以下のようなデータ構造です。
walksテーブルは散歩記録を投稿できる。
timeカラムは、散歩時間を保持
start_timeは、散歩した日付を記録
.以下のようなviewです
散歩記録に関して、「総散歩日数」と「散歩時間」を今月と先月に分けて、それぞれ表示させる
というのが目標です。
#前提知識① groupメソッド
任意の抽出方法でテーブルから値を取得するためにはどうすれば良いのでしょうか。
調べたところ、groupメソッドを使えば実現できそうです。
groupメソッドのポイントは、「指定したカラムごとにデータをまとめる事ができる」という事です。
例えば、性別毎の人数を調べたいとします。
(10人中、男性4人 女性6人のテーブルがあるとする)
その場合
User.group(:sex)
とします。
しかし、このままだと期待する「性別毎のデータ」は取得できません。
User.group(:sex)の実行結果は
User.group(:sex)
SELECT `users`.* FROM `users` GROUP BY `users`.`sex`
=> [#<User:0x007fc281fcae90
id: 3,
name: "user3",
sex: "女性",
age: 58,
#<User:0x007fc281fcad50
id: 1,
name: "user1",
sex: "男性",
]
です。
問題としては
・性別以外のカラムも全て取得してしまっている。
・女性、男性の他のデータは取得できていない。
(処理の裏側では、全てのデータがカラム毎にまとめられています。)
#前提知識② groupメソッドは集計メソッドと併用して使う
そこで、groupメソッドを単体で使用するのではなく、countメソッドやsumメソッドなどの集計メソッドと併用して使う事で、期待するデータ群を取得できます。
例えばcountメソッドを使う事で、
User.group(:sex).count
=> {"女性"=>3, "男性"=>4}
このように性別毎に、データをまとめる事ができました!
※ここまでは以下のサイトを参考にしました。
https://pikawaka.com/rails/group
#groupメソッドで月毎のデータを集計
さてこのgroupメソッドを使って、今月と先月の散歩記録を取得して表示させます。
前提としては
1月の記録は2件、
2月の記録は4件
投稿されています。
今月2月のデータ、投稿数は4件
先月1月のデータ、投稿数は2件
①まずはコントローラーにて、月別でデータを取得します。
class UsersController < ApplicationController
def show
@user = User.find(params[:id])
@month_record =@user.walks.group("MONTH(start_time)")
end
end
「@month_record =@user.walks.group("MONTH(start_time)")」
ユーザーに紐づく散歩記録を、月毎にまとめています。(start_timeは散歩した日付です)
ここでターミナルで@month_record.countとすると、
=> {1=>2, 2=>4}
無事今月のレコードである、2月の投稿分と、1月の投稿分がそれぞれ取得できました。
#取得データをviewで表示
次にviewで取得したデータを表示させます
まず今月の総散歩時間は
countメソッドにDate.today.monthで今月の月を引数に渡す事で実装できました。
@month_record.count[Date.today.month]
次に総散歩時間は、
sumメソッドにtimeカラムを指定すると取得できました。
@month_record.sum(:time)[Date.today.month]
また先月の記録を取得するためには、Date.today.month-1
で表現しました。
以下実装したコード全体です。
<div class=" box">
<h1>今月の散歩記録<h1>
<h4 class ="mt-5">総散散歩日数:<%= @month_record.count[Date.today.month]%>日</h4>
<h4 class ="mt-5">総散歩時間:<%= @month_record.sum(:time)[Date.today.month]%>分</h4>
</div>
<div class ="box">
<h1>先月の散歩記録<h1>
<h4 class ="mt-5">総散歩日数:<%= @month_record.count[Date.today.month-1]%>日</h4>
<h4 class ="mt-5">総散歩時間:<%=@month_record.sum(:time)[Date.today.month-1]%>分</h4>
</div>
実行すると
無事に月毎の散歩記録を表示させる事ができました!
#まとめ
今回は、groupメソッドを使って、月毎のデータを取得する方法について勉強しました。
さらに応用する事で、いろんな状況に対応できそうなので、
また新たな発見があれば投稿します。