1

Okay so September has 30 days right.

This is what rails does when you set an invalid date like 31 September:

s = Student.first
s.date_of_birth = "2015-09-31"

s.save!
> true
s.date_of_birth
> Thu, 01 Oct 2015 00:00:00 UTC +00:00 

It sets the date to 1st of October.

What I want is something like this

 s.save!
   (0.4ms)  BEGIN
   (0.5ms)  ROLLBACK
ActiveRecord::RecordInvalid: Validation failed: Date is not a valid date

Is there no way to force Rails to explicitly error out when setting such a crap date? The standard rails date_select does not dynamically change the number of days in the days dropdown when you change to a different month. So you can select 31 September with the dropdowns, and the date will be saved as 1st of October. But I want to display an error message.

I don't want people to accidentally put the wrong dates into my system.

Marco Prins
  • 7,189
  • 11
  • 41
  • 76

2 Answers2

1

I think one of the solutions would be to change the datatype of date_of_birth from datetime to date. This way Rails would validate the date and would not allow the situation, you've shown.

It is also a good practice to store dates in date type, because it leads to significant decrease in potential issues, when working with those dates.

Andrey Deineko
  • 51,333
  • 10
  • 112
  • 145
  • This solution quietly sets the field to `nil` when the date is nonsensical, which is bad if the field is optional and you'd prefer an error. Looks good for required fields though. – Kristján Nov 26 '15 at 22:44
0

Try adding this to your model:

def date_of_birth=(d)
    date = Date.strptime(d.to_s)
    send(:write_attribute, :date_of_birth, date)
end

Now if you try setting an invalid date, it should raise an exception:

s.date_of_birth = "2015-09-31"   # raises an exception

However, I don't think that doing this is a good idea. It's probably a better idea to do as Andrey Deineko said and store it in a date type.

Amr Noman
  • 2,597
  • 13
  • 24
  • This replaces a Rails error during save with an exception during assignment, so you need two different handling paths everywhere the date can be set. – Kristján Nov 26 '15 at 22:47