MENU

【rails】ActiveSupportの期間指定メソッドを使ってコードがスッキリした話

記事作成から1年以上経過しています。
内容が古い可能性があります。

今日はrailsでスパゲッティコードを便利メソッドでキレイにしたよという話です。

環境

  • ruby 2.6.6
  • rails 5.2.3

参考

【知らずに損した】ActiveSupportの期間指定メソッドall_day, all_week, all_month, all_year
Active Support コア拡張機能

今週の日曜日〜土曜日の期間でデータを取得したい時

使うメソッドとしてはbeginning_of_weekend_of_weekを使って今週の日曜日と今週の土曜日を取得してみましょう。

# 今週日曜日(日曜始まり)を取得するメソッド
irb(main):001:0> Date.today.beginning_of_week
=> 2020-12-06 Dec 2020
# これだと月曜始まりで取得してしまうので-1します
irb(main):002:0> Date.today.beginning_of_week - 1
=> 2020-12-07 Dec 2020
# 日曜日が取れました!

土曜日を取得しましょう。
日付を範囲指定する際に終わりの日にちの何時までを範囲指定する必要がありました. Time.nowを使って土曜日の23:59:59までを指定する範囲に含めるように修正しました. これで0:00:00 ~ 23:59:59のその日1日までを指定した日付の範囲内に含める事ができます。

# 今週土曜日を取得するメソッド
irb(main):003:0> Time.now.end_of_week - 1
=> 2020-12-12 23:59:58 +0900
# 土曜日が取れました!

次に日曜日〜土曜日までのデータを取得してみる

今回はStudyモデルというTBLにid, time, total, user_id, created_atカラムを持つ学習時間を記録するTBLを例に考えます。

カラムタイプ
iddigint
timefloat
totalfloat
user_idinteger
created_atdatetime

このテーブルに以下のデータが入っていると想定します。

irb(main):002:0> Study.all
  Study Load (0.6ms)  SELECT  `studies`.* FROM `studies` LIMIT 11
=> #<ActiveRecord::Relation [#<Study id: 2, time: 0.5, total: 0.5, user_id: nil, created_at: "2020-12-05 11:09:38", updated_at: "2020-12-05 11:09:38">, #<Study id: 3, time: 1.5, total: 2.0, user_id: nil, created_at: "2020-12-07 11:09:42", updated_at: "2020-12-07 11:09:42">, #<Study id: 4, time: 2.0, total: 4.0, user_id: nil, created_at: "2020-12-07 11:09:49", updated_at: "2020-12-07 11:09:49">, #<Study id: 5, time: 0.5, total: 4.5, user_id: nil, created_at: "2020-12-07 11:26:38", updated_at: "2020-12-07 11:26:38">, #<Study id: 6, time: 1.0, total: 5.5, user_id: nil, created_at: "2020-12-07 11:27:31", updated_at: "2020-12-07 11:27:31">, #<Study id: 7, time: 0.5, total: 6.0, user_id: nil, created_at: "2020-12-07 23:16:04", updated_at: "2020-12-07 23:16:04">, #<Study id: 8, time: 1.5, total: 7.5, user_id: nil, created_at: "2020-12-07 23:18:49", updated_at: "2020-12-07 23:18:49">]>

id2~8までの7件のレコードが存在しています(id1が歯抜けしているのは無視して下さいw)

このデータがある状態で先程のメソッドを使って期間を今週に絞ってデータを取得してみたいと思います。

irb(main):003:0> Study.where(created_at: Date.today.beginning_of_week - 1..Time.now.end_of_week - 1).sum(:time)
   (4.1ms)  SELECT SUM(`studies`.`time`) FROM `studies` WHERE `studies`.`created_at` BETWEEN '2020-12-06' AND '2020-12-12 23:59:58'
=> 7.0

whereでcreated_atが今週日曜日(12/6)〜今週土曜日(12/12)までの7日間のデータを取得して、sumメソッドでtimeカラムの合計を計算します。

スパゲッティコードを書く

まず私が最初に書いたスパゲッティコードで書きますw

# studies_controller.rb
~省略~
def index
@this_week_total_time = Study.where(created_at: Date.today.beginning_of_week - 1..Time.now.end_of_week - 1).sum(:time)
end
~省略~

controllerにこんな書いてたらどんどんfatになっていく予感しかしないですし、汚いコードですね。

リファクタリング1

モデルメソッドを使ってcontrollerの見通しをよくします。

# studies_controller.rb
~省略~
def index
@this_week_total_time = Study.this_week_total
end
~省略~

# models / study.rb
~省略~
def this_week_total
self.where(created_at: date.today.beginning_of_week - 1..Time.now.end_of_week - 1).sum(:time)
end
~省略~

ロジック部分をモデルに移行したので、コントローラーがスッキリしました!

本題railsの便利メソッドを使う

コントローラーはキレイになりましたが、モデルメソッドが冗長です。
そこでrailsが用意してくれているall_weekメソッドを使ってリファクタリングしましょう。

# models / study.rb
~省略~
def this_week_total
@today = Time.now
+@range = @today.all_week(:sunday) ← 追加
self.where(created_at: @range).sum(:time)
end
~省略~

all_weekは引数を取ることで任意の曜日始まりにできます.今回は日曜始まりにしたいので(:sunday)を渡します。
最初のコードに比べると大分キレイなコードになりました!
以前のコードだとbeginning_of_week - 1なので、「週の始まりの日付を取得しているけど、-1しているから~えーっと、結局何曜日なの!?」って何ヶ月後の自分が見たら思うでしょうw
リファクタリングした@range = @today.all_week(:sunday)であれば「日曜始まりで期間が今週なんだな」と直感的に分かるようになりました。

念の為、確認してみましょう。

irb(main):006:0> @today = Time.now
=> 2020-12-09 11:25:43 +0900
irb(main):007:0> @range = @today.all_week(:sunday)
=> 2020-12-06 00:00:00 +0900..2020-12-12 23:59:59  +0900
irb(main):008:0> Study.where(created_at: @range).sum(:time)
   (0.5ms)  SELECT SUM(`studies`.`time`) FROM `studies` WHERE `studies`.`created_at` BETWEEN '2020-12-06 00:00:00' AND '2020-12-12 23:59:59'
=> 7.0

ちゃんと指定した期間のデータを取得する事ができました!
公式リファレンスに詳しく書いているので、こちらも合わせて読んでみて下さい!!

終わり

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

ブライダル業界 → 2021年9月 miracleave に転職
未熟者ですが、よろしくお願いいたします!
甘いもの大好きすぎる。。

目次