During the past few days I’ve been busy looking for existing gems doing date validation in Rails 4. I’ve tried a couple of the most famous, but they were compatible with Rails only up to 3.2, so I decided to write a solution myself.
It works fine for me. I’m not going to convert it to a gem because I don’t have time to learn how to right now. If you want to help, you’re welcome.
Docs
It’s all very straightforward.
- The validator symbol is :date.
- The validator really does nothing if you don’t provide any options…
- Supported options are :after, :before, :on_or_after, and :on_or_before, plus :message.
- If the message is not provided a fine default one is used instead.
- Values of supported options can be date-castable objects, lambdas, or symbols.
- Symbols must be method names of the validating object or its class.
- Values are computed (if needed) and converted to date on each validation.
Code
Here is my DateValidator class, to be put into the app/validators folder.
{[ .date-validator | 1.hljs(=ruby=) ]}
Here is an example of how to use it into a model.
{[ .user-profile | 1.hljs(=ruby=) ]}
Here is the form helper snippet (only what differs from scaffolding).
{[ .form-helper | 1.hilite(=html=) ]}
Here is the controller snippet (only what differs from scaffolding).
{[ .controller | 1.hljs(=ruby=) ]}
On line
result[key] = val.to_date
I added
result[key] = val.to_date if val
Thanks for sharing this, it works great. Like Hector I needed to add the
if val
Hi,
what license do you have for this code?
Regards Ester
@Ester, MIT License, the same of Ruby on Rails. It that useful to you?
Can you please release a GEM so that we can use it more seamlessly 😀
Yes, It is useful. You should release a gem.
https://github.com/johncarney/validates_timeliness has the gem compatible with rails 4
Great! But how do I use it with another value on the same record? Cant get this to work, always valid.
http://pastie.org/9374594
@Emil, it doesn’t work your way because when the lambda is called, my code doesn’t pass any argument to it. You should be able to get what you mean by means of an instance method, though.
Here (https://gist.github.com/563a34291d96908bc011) the small upgrade of your code.
Now you can write like this:
validates :begin_date, :date => {
:on_or_before => :end_date, :on_or_before_message => “must be on or before End Date”,
:after => Proc.new{|b| b.begin_date }, :after_message => “must be after Begin Date”
}
Shouldn’t we also check for valid date? Something like: Date.parse(value.to_s) rescue record.errors[attribute] << 'must be a valid date' ?