Rails invalid datetime on model results in nil
activerecord, ruby-on-rails, ruby-on-rails-3, validation
Solution
One workaround would be to move the `allow_nil` part into the `date_time` validation:
class DatetimeValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
return if value.blank?
value.to_datetime rescue record.errors[attribute] << (options[:message] || "must be a date.")
end
end
class Foo
validates :my_date, :datetime => true
end
Edit: I think it's an issue with typecasting - try this (adapted from the code for `validates :numericality`):
def validate_each(record, attribute, value)
before_type_cast = "#{attribute}_before_type_cast"
raw_value = record.send(before_type_cast) if record.respond_to?(before_type_cast.to_sym)
raw_value ||= value
return if raw_value.blank?
raw_value.to_datetime rescue record.errors[attribute] << (options[:message] || "must be a date.")
end
Problem
I have a model with a datetime attribute. I am trying to validate incoming JSON which would update the model. But ActiveRecord seems to be setting the value of the attribute to nil if it is an invalid datetime. I can't respond with the appropriate error because the attribute is allowed to be nil. What am I doing wrong? Code: ``` class DatetimeValidator < ActiveModel::EachValidator def validate_each(record, attribute, value) value.to_datetime rescue record.errors[attribute] << (options[:message] || "must be a date.") end end class Foo # column :my_date, :datetime validates :my_date, :allow_nil => true, :datetime => true end ``` Console: ``` 1.9.3p125 :001 > x = Foo.new => #<Foo id: nil, my_date: nil> 1.9.3p125 :001 > x.my_date = 'bad value' => 'bad value' 1.9.3p125 :001 > x.my_date => nil 1.9.3p125 :001 > x.valid? => true ``` As far as ActiveRecord is concerned, setting the datetime attribute to 'bad_value' is equivalent to setting it to nil, so I can't validate it, since my_date is not required. This seems like a bug to me. What is the best workaround? Thanks!