Rails already does a good job of displaying validation error messages and provides for styling them using CSS.
Maybe you want to display these kinds of errors entirely differently. Let’s say you don’t want to show messages in a single block, instead you’d like to tack them onto the individual fields. Now, you don’t have to change code somewhere deep in the bowels of Rails. A hook for customization is already there: ActionView::Base.field_error_proc. That class variable holds a Proc object that is used to render input elements with errors.
Keep in mind, that this error proc only applies to tags inserted via one of the various helper methods. It does not automagically wrap itself around HTML tags you write manually.
Here’s an example of a field_error_proc that puts the error message in the field’s title. Multiple messages are nicely bulletted.
ActionView::Base.field_error_proc = Proc.new do |html_tag, instance|
msg = instance.error_message
title = msg.kind_of?(Array) ? '* ' + msg.join("\n* ") : msg
"<div class=\"fieldWithErrors\" title=\"#{title}\">#{html_tag}</div>"
end
Where does this code go? A good place is at the end of config/environment.rb. Better still, put it in another file that is included there.
Of course, when validation did result in errors, you can’t count on users to search around with the mouse to see error message. So let’s make it a little easier for them by tinting the background of failing input widgets with an alarming color.
.fieldWithErrors {
display: inline;
}
.fieldWithErrors input, .fieldWithErrors select {
background-color: #ffdfdf;
}
As described so far, the method doesn’t display any error messages related to associated objects chosen through a select or collection_select. The reason for this is that these helpers insert HTML code for setting the value of a foreign key parameter. Say, you have a belongs_to association employer, then this will most likely be realized as a foreign key named employer_id. Now, if there’s an error related to this association, it will be attached to the association’s name, i.e. “employer”, not the name of the foreign key field, “employer_id”. Hence no error message for that field will be easily available for the changed validation display described above.
To get the error message of employer for employer_id, too, there’s a small hack (patch? intercession?) to achieve this
module ActiveRecord
class Errors
alias_method :on_without_id_stripping, :on
def on(attribute)
on_without_id_stripping(attribute.to_s.sub(/_id$/, ''))
end
end
end
—MichaelSchuerig
But a word of caution. If you apply this “intercession” to your code and later run into run-away server process problems (where the server process consumes all available CPU and RAM), take the “intercession” out, restart your server and try again before wasting HOURS trying to find the problem, like I did.
—SheldonHearn
Here’s a little regexp I cooked up to switch the ‘style’ attribute of an input tag in-place. This is handy if you don’t want to wrap your input elements inside a div (wrapping it in a div always seems to mess my layout up a bit):
ActionView::Base.field_error_proc = Proc.new do |html_tag, instance|
msg = instance.error_message
error_style = "background-color: #f2afaf"
if html_tag =~ /<(input|textarea|select)[^>]+style=/
style_attribute = html_tag =~ /style=['"]/
html_tag.insert(style_attribute + 7, "#{error_style}; ")
elsif html_tag =~ /<(input|textarea|select)/
first_whitespace = html_tag =~ /\s/
html_tag[first_whitespace] = " style='#{error_style}' "
end
html_tag
end
An example using the techniques above (and more) is here:
http://www.bigbold.com/snippets/posts/show/1671