---
title: "Rails 6 allows overriding ActiveModel::Errors#full_message"
description:
  "Rails 6 allows to override the ActiveModel::Errors#full_message format at the
  model level and at the attribute level"
canonical_url: "https://www.bigbinary.com/blog/rails-6-allows-to-override-the-activemodel-errors-full_message-format-at-the-model-level-and-at-the-attribute-level"
markdown_url: "https://www.bigbinary.com/blog/rails-6-allows-to-override-the-activemodel-errors-full_message-format-at-the-model-level-and-at-the-attribute-level.md"
---

# Rails 6 allows overriding ActiveModel::Errors#full_message

Rails 6 allows to override the ActiveModel::Errors#full_message format at the
model level and at the attribute level

- Author: Vishal Telangre
- Published: April 22, 2019
- Categories: Rails 6, Rails

## Before Rails 6

Before Rails 6, the default format `%{attribute} %{message}` is used to display
validation error message for a model's attribute.

```ruby

> > article = Article.new
> > => #<Article id: nil, title: nil, description: nil, created_at: nil, updated_at: nil>
> > article.errors.full_message(:title, "cannot be blank")
> > => "Title cannot be blank"
> >
```

The default format can be overridden globally using a language-specific locale
file.

```yaml

# config/locales/en.yml

en:
errors:
format:
"'%{attribute}' %{message}"
```

With this change, the full error message is changed for all the attributes of
all models.

```ruby

> > article = Article.new
> > => #<Article id: nil, title: nil, description: nil, created_at: nil, updated_at: nil>
> > article.errors.full_message(:title, "cannot be blank")
> > => "'Title' cannot be blank"

> > user = User.new
> > => #<User id: nil, first_name: nil, last_name: nil, country: nil, created_at: nil, updated_at: nil>
> > user.errors.full_message(:first_name, "cannot be blank")
> > => "'First name' cannot be blank"
> >
```

This trick works in some cases but it doesn't work if we have to customize the
error messages on the basis of specific models or attributes.

Before Rails 6, there is no easy way to generate error messages like shown
below.

```plaintext
The article's title cannot be empty
```

or

```plaintext
First name of a person cannot be blank
```

If we change the `errors.format` to `The article's %{attribute} %{message}` in
`config/locales/en.yml` then that format will be unexpectedly used for other
models, too.

```yaml

# config/locales/en.yml

en:
errors:
format:
"The article's %{attribute} %{message}"
```

This is what will happen if we make such a change.

```ruby

> > article = Article.new
> > => #<Article id: nil, title: nil, description: nil, created_at: nil, updated_at: nil>
> > article.errors.full_message(:title, "cannot be empty")
> > => "The article's Title cannot be empty"

> > user = User.new
> > => #<User id: nil, first_name: nil, last_name: nil, country: nil, created_at: nil, updated_at: nil>
> > user.errors.full_message(:first_name, "cannot be blank")
> > => "The article's First name cannot be blank"
> >
```

Notice the error message generated for the `:first_name` attribute of User
model. This does not look the way we want, right?

Let's see what is changed in Rails 6 to overcome this problem.

## Enhancements made to `ActiveModel::Errors#full_message` in Rails 6

Overriding the format of error message globally using `errors.format` is still
supported in Rails 6.

In addition to that, Rails 6 now also supports overriding the error message's
format at the model level and at the attribute level.

In order to enable this support, we need to explicitly set
`config.active_model.i18n_customize_full_message` to `true` in the Rails
configuration file, preferably in `config/application.rb` which is implicitly
set to `false` by default.

##### Overriding model level format

We can customize the full error message format for each model separately.

```yaml

# config/locales/en.yml

en:
activerecord:
errors:
models:
article:
format: "`%{attribute}`: %{message}"
user:
format: "%{attribute} of the user %{message}"
```

The full error messages will look like this.

```ruby

> > article = Article.new
> > => #<Article id: nil, title: nil, description: nil, created_at: nil, updated_at: nil>
> > article.errors.full_message(:title, "cannot be empty")
> > => "`Title`: cannot be empty"
> > article.valid?
> > => false
> > article.errors.full_messages
> > => ["`Title`: can't be blank"]

> > user = User.new
> > => #<User id: nil, first_name: nil, last_name: nil, country: nil, created_at: nil, updated_at: nil>
> > user.errors.full_message(:first_name, "cannot be blank")
> > => "First name of the user cannot be blank"

> > comment = Comment.new
> > => #<Comment id: nil, message: nil, author_id: nil, created_at: nil, updated_at: nil>
> > comment.errors.full_message(:message, "is required")
> > => "Message is required"
> >
```

Notice how the default format `%{attribute} %{message}` is used for generating
the full error messages for the `Comment` model since its format is not being
overridden.

Since the other methods such as `ActiveModel::Errors#full_messages`,
`ActiveModel::Errors#full_messages_for`, `ActiveModel::Errors#to_hash` etc. use
the `ActiveModel::Errors#full_message` method under the hood, we get the full
error messages according to the custom format in the returned values of these
methods respectively as expected.

##### Overriding attribute level format

Similar to customizing format at the model level, we can customize the error
format for specific attributes of individual models.

```yaml

# config/locales/en.yml

en:
activerecord:
errors:
models:
article:
attributes:
title:
format: "The article's title %{message}"
user:
attributes:
first_name:
format: "%{attribute} of a person %{message}"
```

With such a configuration, we get the customized error message for the `title`
attribute of the Article model.

```ruby

> > article = Article.new
> > => #<Article id: nil, title: nil, description: nil, created_at: nil, updated_at: nil>
> > article.errors.full_message(:title, "cannot be empty")
> > => "The article's title cannot be empty"
> > article.errors.full_message(:description, "cannot be empty")
> > => "Description cannot be empty"

> > user = User.new
> > => #<User id: nil, first_name: nil, last_name: nil, country: nil, created_at: nil, updated_at: nil>
> > user.errors.full_message(:first_name, "cannot be blank")
> > => "First name of a person cannot be blank"
> > user.errors.full_message(:last_name, "cannot be blank")
> > => "Last name cannot be blank"
> >
```

Note that the error messages for the rest of the attributes were generated using
the default `%{attribute} %{message}` format for which we didn't add custom
formats in the `config/locales/en.yml` manifest.

##### Overriding model level format of deeply nested models

```yaml
# config/locales/en.yml

en:
activerecord:
errors:
models:
article/comments/attachments:
format: "%{message}"
```

```ruby

> > article = Article.new
> > => #<Article id: nil, title: nil, description: nil, created_at: nil, updated_at: nil>
> > article.errors.full_message(:'comments/attachments.file_name', "is required")
> > => "is required"
> > article.errors.full_message(:'comments/attachments.path', "cannot be blank")
> > => "cannot be blank"
> > article.errors.full_message(:'comments.message', "cannot be blank")
> > => "Comments message cannot be blank"
> >
```

##### Overriding attribute level format of deeply nested models

```yaml
# config/locales/en.yml

en:
activerecord:
errors:
models:
article/comments/attachments:
attributes:
file_name:
format: "File name of an attachment %{message}"
```

```ruby

> > article = Article.new
> > => #<Article id: nil, title: nil, description: nil, created_at: nil, updated_at: nil>
> > article.errors.full_message(:'comments/attachments.file_name', "is required")
> > => "File name of an attachment is required"
> > article.errors.full_message(:'comments/attachments.path', "cannot be blank")
> > => "Comments/attachments path cannot be blank"
> >
```

## Precedence

The custom formats specified in the locale file has the following precedence in
the high to low order.

- `activerecord.errors.models.article/comments/attachments.attributes.file_name.format`
- `activerecord.errors.models.article/comments/attachments.format`
- `activerecord.errors.models.article.attributes.title.format`
- `activerecord.errors.models.article.format`
- `errors.format`

---

To learn more, please checkout
[rails/rails#32956](https://github.com/rails/rails/pull/32956) and
[rails/rails#35789](https://github.com/rails/rails/pull/35789).

## Links

- [Human page](https://www.bigbinary.com/blog/rails-6-allows-to-override-the-activemodel-errors-full_message-format-at-the-model-level-and-at-the-attribute-level)
