1
0

More than 1 year has passed since last update.

【Rails6】終了日のバリデーションはValidatorが使える

Posted at

環境

Rails 6.0.1
Ruby 2.6.3
PostgreSQL 11.16

状況

終了日が開始日より先にならないようにバリデーションをかけたい。
開始日は必須パラメータで、終了日はオプション。

before

class Period
  attr_reader :start_date, :end_date

  def initialize(start_date, end_date)
    @start_date = start_date
    @end_date = end_date
  end

  def validate_finish_contract_date!
    return nil if end_date.blank?

    raise ActionController::BadRequest, '不正な終了日です' if end_date.to_date < start_date.to_date
    end_date.to_date
  end
end

after

別クラスに切り出さなくてもカスタムバリデーションValidatorで上記のバリデーションはかけれられる。

注意が必要なのは早期リターンしている部分。
モデルのvaldiatesよりValidatorが先に走るので、開始日を空欄にするとValidatorでエラーで落ちる。
それを回避するためにreturnする。

class EndDateValidator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
    return if record.start_date.nil?

    if value < record.start_date
      record.errors.add(attribute, options[:message] || 'は不正な終了日です')
    end
  end
end
validates :start_date, presence: true
validates :end_date, allow_blank: true, end_date: true

おまけ

Rails7からは

validates :end_date, comparison: { greater_than: :start_date }

と書くだけで今回の終了日のバリデーションがかけられるらしい。

参考

1
0
0

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
1
0