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!
-
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?
-
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`.
-
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...
-
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.
-
Sebastian
8:13 AM on Friday, October 15th, 2010
hey,
thanks for the snippet, saved me some time.
cheers.
-
ionas
2:51 PM on Wednesday, December 15th, 2010
Thank you. works great in conjunction with simple_form
-
Chsurfer
9:07 PM on Friday, March 18th, 2011
Nice tip. Worked great for me.
-
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.
-
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,