tekin.co.uk

Overriding Rails' default validation error message format

This is a followup to my recent lightning talk and writeup about i18n in Rails and how it can be useful even when we’re not translating our applications.

In the talk and writeup I describe how we can change the Active Record error message format from the default of "%{attribute} %{message}" and drop the attribute prefix, giving us more flexibility in how we phrase our error messages. The downside to this is that it results in the default Rails error messages being output as incomplete sentences. It’s since occurred to me that it’s possible to avoid this by replicating the default validation error messages in our app’s locale file with the attribute prefix as part of the message, rather than the format!

So we end up with a locale file that looks something like this:


# app/config/locales/en.yml
en:
  errors:
    # Our overridden message format without the attribute prefix
    format: "%{message}"

    # The Rails default messages, but with the attribute prefix included
    messages:
      inclusion: "%{attribute} is not included in the list"
      exclusion: "%{attribute} is reserved"
      invalid: "%{attribute} is invalid"
      confirmation: "%{attribute} doesn't match %{attribute}"
      accepted: "%{attribute} must be accepted"
      empty: "%{attribute} can't be empty"
      blank: "%{attribute} can't be blank"
      present: "%{attribute} must be blank"
      too_long:
        one: "%{attribute} is too long (maximum is 1 character)"
        other: "%{attribute} is too long (maximum is %{count} characters)"
      password_too_long: "%{attribute} is too long"
      too_short:
        one: "%{attribute} is too short (minimum is 1 character)"
        other: "%{attribute} is too short (minimum is %{count} characters)"
      wrong_length:
        one: "%{attribute} is the wrong length (should be 1 character)"
        other: "%{attribute} is the wrong length (should be %{count} characters)"
      not_a_number: "%{attribute} is not a number"
      not_an_integer: "%{attribute} must be an integer"
      greater_than: "%{attribute} must be greater than %{count}"
      greater_than_or_equal_to: "%{attribute} must be greater than or equal to %{count}"
      equal_to: "%{attribute} must be equal to %{count}"
      less_than: "%{attribute} must be less than %{count}"
      less_than_or_equal_to: "%{attribute} must be less than or equal to %{count}"
      other_than: "%{attribute} must be other than %{count}"
      in: "%{attribute} must be in %{count}"
      odd: "%{attribute} must be odd"
      even: "%{attribute} must be even"

      # Our bespoke error message definitions
      models:
        album:
          title:
            blank: "Enter a title for the album"

With that in place, we’re free to define bespoke validation errors for specific attributes and models without the attribute prefix, whilst also preserving the default error messages as a fallback.

Get more fab content like this straight to your inbox

You'll get an email whenever I have a fresh insight or tip to share. Zero spam, and you can unsubscribe whenever you like with a single click.

More articles on Ruby & Rails

Authored by Published by