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.