Rails 3 "error_messages_for" Replacement

After moving an application or two over to Rails 3 beta4, I quickly realized that I was missing my beloved form error validations. It turns out this helper has been removed for a number of reasons, most of which are quite thoughtful and progressive (although it's still available as a plugin over at github).

The old "error_messages_for" helper generated HTML, messages, content, and was not friendly for people trying to setup multilingual applications. While I agree with all of these points, most of my apps are small enough that I still wanted the easy convenience of a simple validation error helper. So I quickly ended up writing my own simpler version of "error_messages_for"...

Errors_for

# add this to app/helpers/application_helper.rb

  def errors_for(object, message=nil)
    html = ""
    unless object.errors.blank?
      html << "<div class='formErrors #{object.class.name.humanize.downcase}Errors'>\n"
      if message.blank?
        if object.new_record?
          html << "\t\t<h5>There was a problem creating the #{object.class.name.humanize.downcase}</h5>\n"
        else
          html << "\t\t<h5>There was a problem updating the #{object.class.name.humanize.downcase}</h5>\n"
        end    
      else
        html << "<h5>#{message}</h5>"
      end  
      html << "\t\t<ul>\n"
      object.errors.full_messages.each do |error|
        html << "\t\t\t<li>#{error}</li>\n"
      end
      html << "\t\t</ul>\n"
      html << "\t</div>\n"
    end
    html
  end  

I added a basic option to pass in an option second argument that will output as the main message. The rest of the error messages will come directly from the passed in object and can be set in your model's validations. In your view you can use it like this:

<h2>Signup</h2>

<%= form_for(@user) do |f| %>
        
        <%= errors_for(@user, "Opps, unable to add new user").html_safe %>
        
        <%= f.label :email %>
        <%= f.text_field :email %>
        
        <%= f.label :password %>
        <%= f.password_field :password %>
        
        <%= f.label 'Password Confirmation' %>
        <%= f.password_field :password_confirmation %>
        
        <%= f.submit 'Signup' %>
        
<% end %>        

Note the added "html_safe" option. Rails 3 escapes all generated HTML by default, so it's necessary to append this method if you want your HTML to display.

Resulting HTML

<div class='formErrors userErrors'>
                <h5>Opps, unable to add new user</h5>

                <ul>
                        <li>Email is too short (minimum is 6 characters)</li>
                        <li>Email should look like an email address.</li>
                        <li>Password is too short (minimum is 4 characters)</li>
                        <li>Password doesn't match confirmation</li>
                        <li>Password confirmation is too short (minimum is 4 characters)</li>

                </ul>
        </div>

Using this example, it should be easy enough to alter this snippet to suit your needs... thanks for reading and good luck with Rails 3!

  1. 1d206ead0c32cb1fd5869894f25eb91b

    Steve

    9:36 PM on Sunday, July 11th, 2010

    This is great, but what if you want to sprinkle the errors around the form fields? Is there a way to call each error separately?

  2. E884d559ed311e48ec9831b895719b2a

    CowboyCoded

    7:55 PM on Monday, July 26th, 2010

    DEPRECATION WARNING: f.error_messages was removed from Rails and is now available as a plugin. Please install it with `rails plugin install git://github.com/rails/dynamic_form.git`.

  3. 4a24c05eeb9e3ae07ac3a63b5fafa9da

    Emerson Lackey

    1:27 AM on Tuesday, July 27th, 2010

    Thanks for the helpful and friendly message CowboyCoded, I've added a note to this post explaining your comment.

    This being said, it's sometimes useful to avoid introducing another dependency to your application by installing a plugin. It can also be nice to code something yourself so that you fully understand it...

  4. D40bc12523cf0ac31e001afd996f7c33

    slothbear

    3:46 PM on Thursday, September 2nd, 2010

    Thanks for sharing this -- I was able to understand and use the code, and preferred not to use a plugin.

  5. 71800d405648c56d2f8df1e9a212b559

    Sebastian

    8:13 AM on Friday, October 15th, 2010

    hey,

    thanks for the snippet, saved me some time.

    cheers.

  6. 13f645b7b813cc8a1f2c4225b25070c5

    ionas

    2:51 PM on Wednesday, December 15th, 2010

    Thank you. works great in conjunction with simple_form

  7. F9f5505995764bf1a22c6862409d1b0d

    Chsurfer

    9:07 PM on Friday, March 18th, 2011

    Nice tip. Worked great for me.

  8. 1363c22df7e6836fecb93956b04b4765

    Ian

    3:37 PM on Sunday, March 20th, 2011

    Not too difficult to sprinkle them errors around form fields this way. You could use . Alternatively, you could add an extra parameter to the errors_for method that provides information about the field type, and condition the html return certain snippets based off the known field type. Or, even better, object.field_type.errors.blank? and just call the error_for(@user) in each field.

  9. 4e0d7a508ee34c43989c40a25cc65cf1

    pruiz

    9:27 PM on Wednesday, April 13th, 2011

    Hi, very useful snippet. I don't know if this is a bug in rails, but when I use this code within a nested form, and an error occurs, object.class gives me the name of the class in plural, rendering localization useless, since all lookups for attributes names in locale files are done for "class_name_in_plural.attribute_name".

    Any ideas?

    Regards,