質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
date

dateは、date型や日付に関する関数や処理についてのタグです

Model

MVCモデルの一部であるModelはアプリケーションで扱うデータとその動作を管理するために扱います。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

バリデーション

Validationとは特定の入力データが、求められた条件に当てまっているかをチェックするために使われます。

テスト駆動開発

テスト駆動開発は、 プログラム開発手法の一種で、 プログラムに必要な各機能をテストとして書き、 そのテストが動作する必要最低限な実装を行い コードを洗練させる、といったサイクルを繰り返す手法の事です。

Q&A

解決済

1回答

1399閲覧

独自のバリデーションを作り、正常に動作はするがそれまで通っていたミニテストにエラーが発生するようになりました。

kytm

総合スコア11

date

dateは、date型や日付に関する関数や処理についてのタグです

Model

MVCモデルの一部であるModelはアプリケーションで扱うデータとその動作を管理するために扱います。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

バリデーション

Validationとは特定の入力データが、求められた条件に当てまっているかをチェックするために使われます。

テスト駆動開発

テスト駆動開発は、 プログラム開発手法の一種で、 プログラムに必要な各機能をテストとして書き、 そのテストが動作する必要最低限な実装を行い コードを洗練させる、といったサイクルを繰り返す手法の事です。

0グッド

0クリップ

投稿2021/10/21 14:11

スケジュールの作成アプリで日付を入力する際、終了日が開始日よりも前の日だった場合はバリデーションを
通さないようにする為に自作で:end_date_is_before_start_dateというメソッドを作成しました。

また、:end_date_is_before_start_dateに対するテストを先に書き、
それに対しては成功しているのですが、
以前作成した、開始日(start_date)と終了日(end_date)に値が入力されているかのテストでエラーが起きるようになりました。

エラーを見た感じnilに対して"<"を呼び出していることでエラーが起きているようです。

start_dateとend_dateはどちらもDate型で定義しています。

なぜこのようなエラーが起こるのでしょうか?

また、自作でバリデーションを作成する際には
errors.add(:end_date_is_before_start_date,"終了日は今日以降の日付で選択してください")
のようにerrors.addをしなければできないのでしょうか?
なぜif文の条件分岐で場合分けをしてreturnとfalseを返すだけではうまくいかないのでしょうか?

<エラー内容>

1) Error: ScheduleTest#test_end_date_should_be_present: NoMethodError: undefined method `<' for nil:NilClass app/models/schedule.rb:11:in `end_date_is_before_start_date' test/models/schedule_test.rb:24:in `block in <class:ScheduleTest>' 2) Error: ScheduleTest#test_start_date_should_be_present: ArgumentError: comparison of Date with nil failed app/models/schedule.rb:11:in `<' app/models/schedule.rb:11:in `end_date_is_before_start_date' test/models/schedule_test.rb:19:in `block in <class:ScheduleTest>' 10 runs, 9 assertions, 0 failures, 2 errors, 0 skips

<テスト>

test "start_date should be present" do @schedule.start_date = " " assert_not @schedule.valid? end test "end_date should be present" do @schedule.end_date = " " assert_not @schedule.valid? end test "start_date should be before end_date" do @schedule.end_date = Date.new(2021,10,13) assert_not @schedule.valid? end

<モデル>

class Schedule < ApplicationRecord validates :title, presence: true, length: {maximum: 50} validates :start_date, presence: true validates :end_date, presence:true validates :all_day, inclusion: {in: [true, false]} validates :memo, length: {maximum: 100} validate :end_date_is_before_start_date def end_date_is_before_start_date return false if end_date.blank? && start_date.blank? if end_date < start_date errors.add(:end_date_is_before_start_date,"終了日は今日以降の日付で選択してください") end end end

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

ruby

1if end_date < start_date

直前で return false if end_date.blank? && start_date.blank? としていますが、
この条件では end_date か start_date のどちらかが空になる場合があります。

どちらかが空であれば比較はできません。
どちからが空の場合は return するようにします。

ruby

1return false if end_date.blank? || start_date.blank?

どちらかが空で return して validate :end_date_is_before_start_date が通っても、
validates :end_date, presence: true か validates :start_date, presence: true に弾かれます。

errors.add する理由は Railsガイド カスタムメソッド によると

valid?メソッドはerrorsコレクションが空であることを検証するので、カスタムバリデーションはバリデーションが失敗したときにエラーを追加すべきです。

とあります。erros.add しないと valid? が true になってしまうんですね。

投稿2021/10/21 19:05

編集2021/10/21 19:06
neko_daisuki

総合スコア2090

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kytm

2021/10/22 07:52

解決しました。ありがとうございます! なるほどvalid?メソッドはerrorsコレクションが空だった場合にtrueを返し、バリデーションを通す。 errorsコレクションに値が入っていた場合はvalid?にfalseが返り、バリデーションを通さないのですね。 ではここで一つ疑問があるのですが、return false if end_date.blank? || start_date.blank? の判定がtrueになった際はreturnでvalid?にfalseを返し、バリデーション自体をスキップさせることができますが、 errorsコレクションに値が入っていた場合のfalseと事前のreturnでのfalseで動作に違いが起こるのはなぜでしょうか?
neko_daisuki

2021/10/22 14:58

質問の意味がくみ取れているか不安ですが、 カスタムメソッドの戻り値は問題にならないようです。 retrun true しようが、 retrun false しようが同じです。 errors.add の有無のみが valid? に影響します。
kytm

2021/10/22 19:21

なるほど。 retrun true 、 retrun falseの場合はバリデーションそのものを行うか否かに関係し、 errors.addの判定結果がtrueの場合はバリデーション失敗。falseの場合はバリデーション成功となる分けですね。 ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問