I have the following model with a virtual attribute
class Mytimeperiod < ActiveRecord::Base
validates presence of :from_dt
validates_format_of :from_dt, :with => /\A\d{2}\/\d{2}\/\d{4}\Z/, :message => "format is mm/dd/yyyy"
def from_dt
self.from_date.strftime("%m/%d/%Y") if !self.from_date.blank?
end
def from_dt=(from_dt)
self.from_date = Date.parse(from_dt)
rescue
self.errors.add_to_base("invalid from dt")
end
end
I am using <%= f.error_m开发者_StackOverflowessages %>
to display the error messages on the form.
I am using from_dt as a virtual attribute (string). The 'presence of' and 'format of' validation errors show up on the form, but when the user enters an invalid date format on the form and Date.Parse raises an exception I have a 'errors.add_to_base' statement in the rescue clause. Can anyone tell me why this error does not show up in the form error messages when I disable the 'format of' validation.
thanks.
Errors added outside of the validation callbacks will be removed when validation gets run - ActiveModel
So you have to add your errors from within a validation callback, not in a setter. This should work:
class Mytimeperiod < ActiveRecord::Base
validates presence of :from_dt
validates_format_of :from_dt, :with => /\A\d{2}\/\d{2}\/\d{4}\Z/, :message => "format is mm/dd/yyyy"
validate :from_dt_must_parse
def from_dt
self.from_date.strftime("%m/%d/%Y") if !self.from_date.blank?
end
def from_dt=(from_dt)
self.from_date = Date.parse(from_dt)
rescue
@from_dt_parse_error = "not recognizable as a date"
end
def from_dt_must_parse
self.errors[:from_dt] = @from_dt_parse_error
end
end
Your syntax looks OK. If you're having issues testing in the console, make sure to do reload!
(or exit and run script/console
again).
If the only reason you're using a virtual attribute is to validate the date format, don't forget you can make your own validations with the validate
method (untested):
class Mytimeperiod < ActiveRecord::Base
protected
def validate
date = Date.parse(from_date)
rescue
errors.add("from_date", "date is invalid")
end
end
This has the advantage of adding errors to the field rather than the object.
I believe the problem is actually just your syntax, you need to start add a begin
to the start of the block that has the rescue
:
def from_dt=(from_dt)
begin
self.from_date = Date.parse(from_dt)
rescue
self.errors.add_to_base("invalid from dt")
end
end
精彩评论