行動すれば次の現実

テック中心の個人ブログ

Railsのカスタムバリデーションで複数項目の相関をチェックしたい

開始日と終了日を入力するシステムで、期間の大小チェックと期間の日数チェックを行いたい場合があります。

カスタムメソッドで実装するケースはよく見受けられますが、カスタムバリデーションとして使い回したい思ったので実装してみました。

※あくまでも簡易実装なので国際化などは非対応です。

日付期間チェックのカスマムバリデータ

class DatePeriodValidator < ActiveModel::Validator
  def validate(record)
    start_date, end_date, max_days_period_val = options.values_at(:start_date, :end_date, :max_days_period)
    start_date_val = record.send(start_date)
    end_date_val = record.send(end_date)
    return if start_date_val.blank? || end_date_val.blank?

    if max_days_period_val.present? && (start_date_val - end_date_val).to_i.abs > max_days_period_val
      return record.errors[options[:start_date]] << "#{record.class.human_attribute_name(end_date)}の期間は#{max_days_period_val}日以内を入力してください"
    end

    return if start_date_val <= end_date_val

    record.errors[options[:start_date]] << "#{record.class.human_attribute_name(end_date)}よりも前に設定してください"
  end
end

使い方

対象のモデルに以下のような宣言を追加します。

validates_with DatePeriodValidator, start_date: :sales_start_date, end_date: :sales_end_date, max_days_period: 31
  • start_date:(必須) 開始日にあたる対象のカラム名を指定してください
  • end_date:(必須) 終了日にあたる対象のカラム名を指定してください
  • max_days_period:(任意) 有効な期間の日数を指定してください。未指定の場合は期間日数チェックは行いません。