This morning I experimented a bit with overriding the default HTML generated by validation errors in Rails. Instead of wrapping the <input> tag inside a <div class="fieldWithErrors"> indiscriminately (which was breaking the layout I wanted), I wanted to simply inject a new CSS class onto the HTML element.

I found one email showing how to use regular expressions to get the job done. It may work, but I wanted something that seemed a little less blunt. I’ve also been playing around with Hpricot lately as well. So I decided to try to combine the two. Here’s the first draft of what I came up with:

require 'hpricot'

Rails::Initializer.run do |config|
  . . .
  ActionView::Base.field_error_proc = Proc.new do |html_tag, instance|
    doc = Hpricot(html_tag)
    elem = (doc/"/").first
    css_class = elem.attributes['class']
    css_class ||= ""
    css_array = css_class.split(" ")
    css_array << "fieldWithErrors"
    elem.attributes['class'] = css_array.uniq.join(" ")
    doc.to_s
  end
end

I then changed the CSS ever so slightly from the default scaffold.css:

.fieldWithErrors {
  border-color: red;
  background-color: #ffcccc;
}

The result looks like this:

Rails form with custom CSS class on model validation failure.

The layout I had before is completely preserved, and I have the chance to color the input the way I want. I haven’t tried it with a <textarea>. Also, I tried to adjust for the possibility of other CSS classes already existing on the element, but I’ve only checked it in irb. Let me know if you’ve got improvements to this approach; I’d love to hear ‘em.