---
title: "Rails 7.1 adds ActiveRecord::Base::normalizes"
description: "Rails 7.1 adds ActiveRecord::Base::normalizes."
canonical_url: "https://www.bigbinary.com/blog/rails-7-1-adds-activerecord-base-normalizes"
markdown_url: "https://www.bigbinary.com/blog/rails-7-1-adds-activerecord-base-normalizes.md"
---

# Rails 7.1 adds ActiveRecord::Base::normalizes

Rails 7.1 adds ActiveRecord::Base::normalizes.

- Author: Abhijith Sheheer
- Published: May 9, 2023
- Categories: Rails, Rails 7

Rails 7.1 has introduced a new method in Active Record that can be used to
declare normalizations for attribute values. This can be especially useful for
sanitizing user input, ensuring consistent formatting, or cleaning up data from
external sources.

Before Rails 7.1, you could normalize attributes using `before_save` callback.

```ruby
model User < ApplicationRecord
  before_save :downcase_email, if :email_present?

  private

    def email_present?
      email.present?
    end

    def downcase_email
      email.downcase!
    end
end
```

In Rails 7.1, you can refactor the above to the code below.

```ruby
model User < ApplicationRecord
  normalizes :email, with: -> email { email.downcase }
end
```

The normalization is applied when the attribute is assigned or updated, and the
normalized value will be persisted to the database. The normalization is also
applied to the corresponding keyword argument of finder methods. This allows a
record to be created and later queried using unnormalized values.

By default, normalization is not applied to `nil` values. To normalize `nil`
value, you can enable it using `:apply_to_nil` option.

```ruby
model User < ApplicationRecord
  normalizes :user_name, with:
    -> user_name { user_name.parameterize.underscore }

  normalizes :email, with: -> { _1.strip.downcase }

  normalizes :profile_image, with:
    -> profile_image {
      profile_image.present? ? URI.parse(profile_image).to_s :
      "https://source.boringavatars.com/beam" },
    apply_to_nil: true
end
```

```ruby
# rails console
>> User.create!(user_name: "Eve Smith", email: "eveSmith@EXAMPLE.com")

#<User:0x000000010b757090 id: 1, user_name: "eve_smith", profile_image:"https://source.boringavatars.com/beam", email: "evesmith@example.com", created_at: Wed, 03 May 2023 07:49:20.067765000 UTC +00:00, updated_at: Wed, 03 May 2023 07:49:20.067765000 UTC +00:00>

>> user = User.find_by!(email: "EVESMITH@example.COM")
>> user.email # => "evesmith@example.com"

>> User.exists?(email: "EveSmith@Example.COM")          # => true
```

If a user's email was already stored in the database before the normalization
statement was added to the model, the email will not be retrieved in the
normalized format.

This is because in the database it's stored in mixed case, that is, without the
normalization. If you have legacy data, you can normalize it explicitly using
the `Normalization#normalize_attribute` method.

```ruby
# rails console
>> legacy_user = User.find(1)
>> legacy_user.email  # => "adamSmith@EXAMPLE.com"
>> legacy_user.normalize_attribute(:email)
>> legacy_user.email  # => "adamsmith@example.com"
>> legacy_user.save
```

Please check out this [pull request](https://github.com/rails/rails/pull/43945)
for more details.

## Links

- [Human page](https://www.bigbinary.com/blog/rails-7-1-adds-activerecord-base-normalizes)
