How to validate a model's date attribute against a specific range (evaluated at run time)
date, ruby-on-rails, validation
Solution
If the validation is the same for each class, the answer is fairly simple: put a validation method in a module and mix it in to each model, then use `validate` to add the validation:
# in lib/validates_dated_on_around_now
module ValidatesDatedOnAroundNow
protected
def validate_dated_around_now
# make sure dated_on isn't more than five years in the past or future
self.errors.add(:dated_on, "is not valid") unless ((5.years.ago)..(5.years.from_now)).include?(self.dated_on)
end
end
class FirstModel
include ValidatesDatedOnAroundNow
validate :validate_dated_around_now
end
class SecondModel
include ValidatesDatedOnAroundNow
validate :validate_dated_around_now
end
If you want different ranges for each model, you probably want something more like this:
module ValidatesDateOnWithin
def validates_dated_on_within(&range_lambda)
validates_each :dated_on do |record, attr, value|
range = range_lambda.call
record.errors.add(attr_name, :inclusion, :value => value) unless range.include?(value)
end
end
end
class FirstModel
extend ValidatesDatedOnWithin
validates_dated_on_within { ((5.years.ago)..(5.years.from_now)) }
end
class SecondModel
extend ValidatesDatedOnWithin
validates_dated_on_within { ((2.years.ago)..(2.years.from_now)) }
end
Problem
I have several models with a date attribute and for each model I'd like to validate these dates against a given range. A basic example would be: ``` validates_inclusion_of :dated_on, :in => Date.new(2000,1,1)..Date(2020,1,1) ``` Ideally I'd like to evaluate the date range at runtime, using a similar approach as `named_scope` uses, e.g: ``` validates_inclusion_of :dated_on, :in => lambda {{ (Date.today - 2.years)..(Date.today + 2.years)}} ``` The above doesn't work of course, so what is the best way of achieving the same result?