LoginSignup
2
0

More than 1 year has passed since last update.

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

Last updated at Posted at 2022-02-12

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

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

Image from Gyazo

.以下のようなviewです
Image from Gyazo
散歩記録に関して、「総散歩日数」と「散歩時間」を今月と先月に分けて、それぞれ表示させる
というのが目標です。

#前提知識① 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
先月1月のデータ、投稿数は2件
Image from Gyazo

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

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

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

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

2
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0