Reputation: 599
What is the best way to validate a date in Ruby on Rails? I need to make sure the "birthday" is a date, is less than 125 years ago and is not in the future (today is ok).
I have tried three methods:
1) date_validator gem
I used the following code (after installing the gem):
validates :birthday,
date: {
after: Proc.new {Time.now - 125.years}, message: :after,
before: Proc.new {Time.now}, message: :cannot_be_in_the_future
}
This worked except that I could set the date to the number 12 and pass validation.
2) Checking if the date is in a range of dates, in a custom validation method, like so:
from = 125.years.ago.to_date
to = Time.now.to_date
unless (from..to).include? birthday
errors.add(:birthday, :custom_error_msg)
end
This worked well and passed all my tests, but the drawback is that you only get one error message. I would have liked separate error messages for the case when the date is in the future, when it is too long ago and when the input is not a date.
3) Multiple checks in a custom validation method, like so:
begin
birthday.to_date
rescue
errors.add(:birthday, "must be a date")
else
if birthday > Time.now
errors.add(:birtday, "cannot be in the future")
elsif birthday < Time.now - 125.years
errors.add(:birthday, "cannot be over 125 years ago")
end
end
This also passes all my test, and I get different messages as explained above.
So I am wondering, is this the best method? Can it be improved at all (except that the error message text needs work)?
Thanks
Upvotes: 2
Views: 9066
Reputation: 66
You can easily use validates_each method Just put there 2 validations:
1) For birthday in the past
validates_each :birthday do |record, attr, value|
record.errors.add(attr, 'must be in the past') if value >= Time.now.to_date
end
2) For birthday not more than 150 years ago
validates_each :birthday do |record, attr, value|
record.errors.add(attr, 'must be less than 150 years in the past')
if value <= (Time.now.to_date - 125.years)
end
Upvotes: 1
Reputation: 4251
For this simple validation, I think following ruby code is enough!
Please check :
validate :is_valid_dob?
private
def is_valid_dob?
if((birthday.is_a?(Date) rescue ArgumentError) == ArgumentError)
errors.add(:birthday, 'Sorry, Invalid Date of Birth Entered.')
end
end
Upvotes: 4
Reputation: 15146
Just use gem 'validates_timeliness'
In your case, using this gem
validates_date :birthday, on_or_after: lambda { 125.years.ago }
Upvotes: 1