環境
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 }
と書くだけで今回の終了日のバリデーションがかけられるらしい。
参考