【Rails】1日に記録できる数値の合計を制限するバリデーション
はじめに
投稿3回目です。
文章力が赤ちゃんレベルかつ遅筆なのでまだ慣れないです...
間違い等あればご指摘よろしくお願いします。
環境
- Ruby 2.6.3
- Rails 5.2.4
背景/目的
- ポートフォリオで学習内容を記録するサイトを開発中。
- 学習内容は1日に何回でも記録可能であり、項目には学習時間がある。
- 学習時間の合計値が24時間/1日を超えないようにバリデーションを設定する。
- 学習内容(learningsテーブル)の詳細は下記の通り。
カラム名 | データ型 | 説明 |
---|---|---|
date | date | 学習日 |
time | float | 学習時間 |
結論
class Learning < ApplicationRecord
# 一つのユーザー(user)に対して、複数の学習記録(learning)が結びついている
belongs_to :user
# validateに定義したメソッドを設定
validate :total_time_cannot_exceed_limit_time, on: :create
validate :total_time_cannot_exceed_limit_time_for_edit, on: :update
# 1日に記録できる学習時間の合計
LIMIT_TIME_HOUR = 24
# 入力された学習日に既に記録されている学習時間の合計値を取得する
def one_day_time_sum(date)
user.learnings.where(date: date).sum(:time)
end
# 入力された学習日に既に記録されている「編集対象の投稿以外の」学習時間の合計値を取得する
def one_day_time_sum_unless_target_date(date)
user.learnings.where(date: date).where.not(id: id).sum(:time)
end
# create時のカスタムバリデーション用のメソッドを定義
def total_time_cannot_exceed_limit_time
# [学習日が入力済]かつ[学習時間が入力済]かつ[学習日に既に記録された学習時間と入力した学習時間の合計が24時間を超える場合]
if date.presence && time.presence && one_day_time_sum(date) + time > LIMIT_TIME_HOUR
# エラーメッセージを表示する
errors.add(:date, ":#{date.strftime("%Y年%m月%d日")}の学習時間の合計が#{LIMIT_TIME_HOUR}時間を超えています")
end
end
# update時のカスタムバリデーション用のメソッドを定義
def total_time_cannot_exceed_limit_time_for_edit
# [学習日が入力済]かつ[学習時間が入力済]かつ[学習日に既に記録された「編集対象の投稿以外の」学習時間と入力した学習時間の合計が24時間を超える場合]
if date.presence && time.presence && one_day_time_sum_unless_target_date(date) + time > LIMIT_TIME_HOUR
errors.add(:date, ":#{date.strftime("%Y年%m月%d日")}の学習時間の合計が#{LIMIT_TIME_HOUR}時間を超えています")
end
end
end
createとupdateで処理を分けています。
コメントで処理の内容を記載しましたが、自分で読んでても正直よく分からないです。
例えば、下記のデータが既に保存されており、学習日2021-01-01
・学習時間4
の投稿を新たにする場合、
id | 学習日 | 学習時間 |
---|---|---|
1 | 2021-01-01 | 10.6 |
2 | 2021-01-01 | 11.4 |
入力された学習日2021-01-01
に既に記録されている学習時間の合計値22
時間を取得し、入力した学習時間4
時間を足して、24時間と比較します。=> この場合26時間なのでエラーメッセージが表示されます。
これをupdateでも同じ処理にすると動作がおかしくなります。
例えば、id:1
の学習時間を5
時間に変更する場合、5 + 11.4 = 16.4
時間になるのが理想です。
しかし、実際は10.6 + 11.4 + 5 = 27
時間でNGになってしまいます。
user.learnings.where(date: date).sum(:time)
だと編集前の学習時間も取得してしまうので、update時はwhere.not(id: id)
を追記し、編集対象の投稿以外の学習時間の合計を取得するようにしています。
参考にさせていただきました
ここまで見て頂きありがとうございました。
ネーミングセンスがないのは許していただけると助かります😰
Author And Source
この問題について(【Rails】1日に記録できる数値の合計を制限するバリデーション), 我々は、より多くの情報をここで見つけました https://qiita.com/yasu_yk/items/41b0439b6504b9e3654d著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .