tekin.co.uk

Overriding Rail's default 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 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 error messages in our apps 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:
      model_invalid: "Validation failed: %{errors}"
      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 error messages 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