Inline error messages with Rails 3

I was recently tasked with converting a Rails app from Rails 2.3.x to 3.2.x.

“Shouldn’t be too difficult” I thought, but one of the first things that came out and bit me is that the error_message_on helper method, which was previously used to display error messages next to the form fields that had caused them, has been deprecated.

It took me a little while to figure out how to reinstate this functionality. Here’s how I did it.

First off, we should probably note, that although this method has been removed from Rails, it is now available as a plugin named dynamic_form. This means that you could just add ‘dynamic_form’ to your gem file, run bundler and everything would be the same as before.

However, as Ryan Bates notes in Railscast 211 (Validations in Rails 3), the reason that this and a couple of other methods (such as error_messages_for) have been removed, is that the display of error messages often needs to be customized and doing this through the old methods was a little bit cumbersome.

Instead we now have access to @resource.errors which is an instance of the class ActiveModel::Errors containing all errors for a particular resource, where each key is the attribute name and the value is an array of strings with all errors.

That means that we can now write:

<% if @resource.errors[:field_name] %>
 <span class="formError"><%= @resource.errors[:field_name][0] %></span>
<% end %>

and have our errors reappear back inline.

Note, that it is necessary to write [:field_name][0], as @resource.errors[:field_name] is an array containing all available error messages and it is probably not a good idea to display all of these to your users in one go.

Now, this is all a bit verbose, so it is a good idea to move this code into a helper method.

def error_message_for(field, options = {:prepend_text => ""})
  error_message = @resource.errors[field][0]
  if error_message
    raw "#{options[:prepend_text]} #{error_message}"

Now you can just write:

<%= error_message_for(:field_name, :prepend_text => "Whatever ") %>


This post currently has one response

  1. Nick says:

    Perfect ! Exactly what i was looking for !

Comments are closed!

I'm on Twitter: