『Rails』 groupメソッドで、月毎のデータを取得する方法

#はじめに
[![Image from Gyazo](https://i.gyazo.com/fa26b7b1ee177f50e1c80d007d24d666.jpg)](https://gyazo.com/fa26b7b1ee177f50e1c80d007d24d666)
　現在オリジナルアプリ「morning-walk」という朝散歩を習慣化するアプリを制作中です。
その中で、月毎の散歩日数と散歩時間を集計する実装を行ったので、まとめます。

#前提条件
・以下のようなデータ構造です。
walksテーブルは散歩記録を投稿できる。
timeカラムは、散歩時間を保持
start_timeは、散歩した日付を記録

[![Image from Gyazo](https://i.gyazo.com/75afeda9f7b95a523825a7e3974e2bce.png)](https://gyazo.com/75afeda9f7b95a523825a7e3974e2bce)

.以下のようなviewです
[![Image from Gyazo](https://i.gyazo.com/7c0bf7d4bd73cf4c8fc0d328f0c447e8.png)](https://gyazo.com/7c0bf7d4bd73cf4c8fc0d328f0c447e8)
**散歩記録に関して、「総散歩日数」と「散歩時間」を今月と先月に分けて、それぞれ表示させる**
というのが目標です。

#前提知識① groupメソッド　
　任意の抽出方法でテーブルから値を取得するためにはどうすれば良いのでしょうか。
調べたところ、groupメソッドを使えば実現できそうです。
groupメソッドのポイントは、「指定したカラムごとにデータをまとめる事ができる」という事です。

例えば、性別毎の人数を調べたいとします。
（10人中、男性4人　女性6人のテーブルがあるとする）
その場合

```
 User.group(:sex)
```
とします。

しかし、このままだと期待する「性別毎のデータ」は取得できません。

 User.group(:sex)の実行結果は

```@qiita.rb
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メソッドを使う事で、

```qiita.rb
 User.group(:sex).count
=> {"女性"=>3, "男性"=>4}
```
このように性別毎に、データをまとめる事ができました！


※ここまでは以下のサイトを参考にしました。
https://pikawaka.com/rails/group

#groupメソッドで月毎のデータを集計
　さてこのgroupメソッドを使って、今月と先月の散歩記録を取得して表示させます。

前提としては
1月の記録は2件、
2月の記録は4件
投稿されています。

**今月2月のデータ、投稿数は4件** 
[![Image from Gyazo](https://i.gyazo.com/9a6e9480850218b2a499c873ebb300b4.png)](https://gyazo.com/9a6e9480850218b2a499c873ebb300b4)
**先月1月のデータ、投稿数は2件**
[![Image from Gyazo](https://i.gyazo.com/ada07cc8d53a891404485bc77b2eeebc.png)](https://gyazo.com/ada07cc8d53a891404485bc77b2eeebc)

①まずはコントローラーにて、月別でデータを取得します。

```users_controller.rb
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で今月の月を引数に渡す事で実装できました。

```show.html.rb
@month_record.count[Date.today.month]
```

次に総散歩時間は、
sumメソッドにtimeカラムを指定すると取得できました。

```show.html.rb
@month_record.sum(:time)[Date.today.month]
```

また先月の記録を取得するためには、Date.today.month-1
で表現しました。

以下実装したコード全体です。

```show.html.rb
<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>
```

実行すると

[![Image from Gyazo](https://i.gyazo.com/40be67ba510d7e26e715845aba798846.png)](https://gyazo.com/40be67ba510d7e26e715845aba798846)

無事に月毎の散歩記録を表示させる事ができました！


#まとめ
　今回は、groupメソッドを使って、月毎のデータを取得する方法について勉強しました。
さらに応用する事で、いろんな状況に対応できそうなので、
また新たな発見があれば投稿します。