Class: DateValidator

Inherits:
ActiveModel::EachValidator
  • Object
show all
Defined in:
lib/validators/date_validator.rb

Overview

Validate if a column is a valid date, and if it’s before or after another date.

validates :date_column, date: true

We use a lambda for these checks because otherwise Date.today would be evaluated only on startup, and not every time we run the validations (you never want this).

validates :date_column, date: { after: -> { Date.today } }
validates :date_column, date: { after_or_equal_to: -> { Date.today } }
validates :date_column, date: { equal_to: -> { Date.today } }
validates :date_column, date: { before: -> { Date.today } }
validates :date_column, date: { before_or_equal_to: -> { Date.today } }

Check if the column ‘enddate` is after the value of the column `begindate`

validates :begindate, date: true
validates :enddate, date: { after: :begindate }

Constant Summary collapse

CHECKS =
{
  after: :>,
  after_or_equal_to: :>=,
  equal_to: :==,
  before: :<,
  before_or_equal_to: :<=,
}.freeze

Instance Method Summary collapse

Instance Method Details

#validate_each(record, attribute, raw_value) ⇒ Object



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/validators/date_validator.rb', line 50

def validate_each record, attribute, raw_value
  value = value_to_date raw_value

  unless value
    record.errors.add attribute, (options[:message] || I18n.t('rails_validations.date.invalid'))
    return
  end

  options.slice(*CHECKS.keys).each do |option, raw_option_value|
    option_value = if raw_option_value.respond_to? :call
                     if raw_option_value.parameters == []
                       raw_option_value.call
                     else
                       raw_option_value.call record
                     end
                   elsif raw_option_value.is_a? Symbol
                     value_to_date record.send(raw_option_value)
                   elsif raw_option_value.is_a? Integer
                     time.at(raw_option_value).to_date
                   elsif raw_option_value.respond_to? :to_date
                     raw_option_value.to_date
                   else
                     raise ArgumentError
                   end

    unless option_value
      record.errors.add attribute, (options[:message] || I18n.t('rails_validations.date.invalid'))
      return
    end

    unless value.send CHECKS[option], option_value
      record.errors.add attribute, (options[:message] || I18n.t("rails_validations.date.#{option}", date: I18n.l(option_value)))
    end
  end
end

#value_to_date(raw_value) ⇒ Object



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/validators/date_validator.rb', line 29

def value_to_date raw_value
  # TODO: Do we need to do anything with timezones? Figure it out (rails has
  # ActiveSupport::TimeWithZone)...
  if raw_value.is_a? Integer
    time.at(raw_value).to_date
  elsif raw_value.respond_to? :to_date
    begin
      raw_value.to_date
    rescue
      false
    end
  else
    begin
      Date.parse raw_value
    rescue
      false
    end
  end
end