Matt's Blog

Non-Field-Specific Custom Validations and Error Messages in Rails

by Matt Hodan on November 30, 2010

If you’ve created a moderately complex form in Rails, you’ve probably asked yourself the question:

How do I display a validation error message that doesn’t relate to a specific field on my form?

The first solution you should consider is the “error_messages_for” helper. You can use “error_messages_for” in your view to display a quick and dirty summary of all validation errors. For example, the following would display a summary of all validation errors on our application’s “user” model:

<%= error_messages_for :user %>

While not perfect, “error_messages_for” can be customized to show a pretty concise and user friendly error message. Check out the docs to see all of the output customization options:

http://apidock.com/rails/ActionView/Helpers/ActiveRecordHelper/error_messages_for

What if you only want to show one error message in a specific location that relates to a specific validation? Enter the good old “error_message_on” helper. You’ve probably already used “error_message_on” to display field-specific error messages. Here is an example that would display an error message on a name field:

<%= form_for @user do |f| %>
  <%= f.text_field :name %>
  <%= f.error_message_on :name %>
<% end %>

What many people don’t realize is that you can also use “error_message_on” to display non-field-specific error messages. Consider the following custom validation that checks if a user is both “happy” and “broke”:

class User < ActiveRecord:Base
  validate :user_is_happy_and_broke

private
  def user_is_happy_and_broke
    if self.state_of_mind != 'happy' || self.fiscal_status != 'broke'
      errors.add :user_not_happy_and_broke, 'User must be happy and broke to continue'
    end
  end
end

Now, to display this custom validation error message with “error_message_on”, we simply need to reference “:user_is_happy_and_broke” when we call the helper. Consider this implementation:

<%= form_for @user do |f| %>
  <%= f.error_message_on :user_not_happy_and_broke %>
<% end %>

Now just format the output with CSS and you are good to go.


comments powered by Disqus

Recent Articles