How do I validate a date in rails?
Solution 1
I'm guessing you're using the date_select
helper to generate the tags for the date. Another way you could do it is to use select form helper for the day, month, year fields. Like this (example I used is the created_at date field):
<%= f.select :month, (1..12).to_a, selected: @user.created_at.month %>
<%= f.select :day, (1..31).to_a, selected: @user.created_at.day %>
<%= f.select :year, ((Time.now.year - 20)..Time.now.year).to_a, selected: @user.created_at.year %>
And in the model, you validate the date:
attr_accessor :month, :day, :year
validate :validate_created_at
private
def convert_created_at
begin
self.created_at = Date.civil(self.year.to_i, self.month.to_i, self.day.to_i)
rescue ArgumentError
false
end
end
def validate_created_at
errors.add("Created at date", "is invalid.") unless convert_created_at
end
If you're looking for a plugin solution, I'd checkout the validates_timeliness plugin. It works like this (from the github page):
class Person < ActiveRecord::Base
validates_date :date_of_birth, on_or_before: lambda { Date.current }
# or
validates :date_of_birth, timeliness: { on_or_before: lambda { Date.current }, type: :date }
end
The list of validation methods available are as follows:
validates_date - validate value as date
validates_time - validate value as time only i.e. '12:20pm'
validates_datetime - validate value as a full date and time
validates - use the :timeliness key and set the type in the hash.
Solution 2
Using the chronic gem:
class MyModel < ActiveRecord::Base
validate :valid_date?
def valid_date?
unless Chronic.parse(from_date)
errors.add(:from_date, "is missing or invalid")
end
end
end
Solution 3
If you want Rails 3 or Ruby 1.9 compatibility try the date_validator gem.
Solution 4
Active Record gives you _before_type_cast
attributes which contain the raw attribute data before typecasting. This can be useful for returning error messages with pre-typecast values or just doing validations that aren't possible after typecast.
I would shy away from Daniel Von Fange's suggestion of overriding the accessor, because doing validation in an accessor changes the accessor contract slightly. Active Record has a feature explicitly for this situation. Use it.
Solution 5
A bit late here, but thanks to "How do I validate a date in rails?" I managed to write this validator, hope is useful to somebody:
Inside your model.rb
validate :date_field_must_be_a_date_or_blank
# If your field is called :date_field, use :date_field_before_type_cast
def date_field_must_be_a_date_or_blank
date_field_before_type_cast.to_date
rescue ArgumentError
errors.add(:birthday, :invalid)
end
jessica
Updated on August 18, 2021Comments
-
jessica almost 3 years
I created the following cli in order to delete the logs with date format that oldest then 500 min
date format is:
data-node.log.xxxx-xx-xx-[1-10]
the cli that should removed the logs
find /var/log/test/ -type f -mmin +500 -regextype sed -regex '.*\.log\.[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}-[0-9]\{2,10\}$' -delete
as we can see the logs still exists
ls -l /var/log/test/ -rw-r--r-- 1 root root 0 10:02 data-node.log.2019-12-14 -rw-r--r-- 1 root root 0 10:02 data-node.log.2019-12-15 -rw-r--r-- 1 root root 0 10:02 data-node.log.2019-06-16 -rw-r--r-- 1 root root 0 10:02 data-node.log.2020-01-17 -rw-r--r-- 1 root root 0 10:05 data-node.log.2020-01-1723 -rw-r--r-- 1 root root 0 10:05 data-node.log.2020-01-172334 -rw-r--r-- 1 root root 0 10:05 data-node.log.2020-01-17233434 -rw-r--r-- 1 root root 0 10:05 data-node.log.2020-01-1723343434
where I am wrong?
-
Dan Rosenstark almost 15 yearsI don't know if I'll use this for this purpose, but it's a great suggestion.
-
Roger over 14 yearsThe suggested solution does not work for me and I am using Rails 2.3.5
-
Jack Chu about 14 yearsI rewrote it to be cleaner, and tested it against Rails 2.3.5 and this does work for me.
-
benoitr about 13 yearsHi Jack, I've tried your solution, it works for me adding attr_accessible :day, :month, :year. Which doesn't make sense for me... Thanks if you have any idea!
-
Calvin almost 12 yearsIn this specific example, I had to use
Chronic.parse(from_date_before_type_cast)
in order to get the string value input. Otherwise Rails would typecast the string withto_date
since the field was adatetime
field. -
Jason Swett almost 12 yearsIn Rails 3, I'm using github.com/adzap/validates_timeliness and it's awesome.
-
mjnissim almost 12 yearsThe validates_timeliness plugin/gem is really nice to use. Works a charm and keeps my code smaller. Thanks for the tip.
-
jflores over 11 yearsI just tried this. Took all of 2 minutes to install and add validation!
-
Mohamad about 11 yearsThis always returns false:
"1/1/2013".is_a?(Date)
- The date comes from user input, so it's being fed as a string. I'd have to parse it as a date first? -
Trip about 11 yearsCorrect.
Date.parse("1/1/2013").is_a?(Date)
, but you could see that if it doesn't parse at all, its also probably not a date. -
Mohamad about 11 yearsNeed to rescue argument error... ahh, it would have been awesome if it just parsed the string automatically... oh well, there are gem's for that.
-
Pinal almost 10 yearsWhile this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes.
-
Ryan Duffield almost 10 yearsI like my answer better. Two people agree.
-
Wayne Conrad over 9 years@Pinal The link is indeed dead now.
-
fatfrog about 3 yearsBetter late than never, and in time for me!