Before Rails 7.1
Once upon a time, way long before the Rails 7.1 era, a smart Rails developer (like yourself) needed to ensure user email addresses were properly normalized (sanitized and formatted correctly). Back then, they used clever techniques such as callbacks like before_save and before_validation, attribute setters, or even the normalize gem to get the job done. Here are some of those old tricks and tips on how they used to do it.
# normalize with before_save callback class User < ApplicationRecord before_save :sanitize_email private def sanitize_email self.email = email.strip.downcase end end # normalize with before_validation callback class User < ApplicationRecord before_validation :sanitize_email private def sanitize_email self.email = email.strip.downcase end end # override the setter from ActiveRecord class User < ApplicationRecord def email=(value) super(value.strip.downcase) end end # Don't like callbacks? Use the normalize gem in `app/normalizers` class EmailNormalizer def self.call(email) email.strip.downcase end end class User < ApplicationRecord normalize :email, with: EmailNormalizer end
After Rails 7.1
As time passed, the Rails community reached the Rails 7.1 era. A group of those smart Rails developers (maybe it's you) gathered around the Rails core team and agreed on a better way to normalize attributes. They came up with a nifty idea.
Imagine having a ClassMethod `normalizes` that comes with a set of rules, such as converting all email addresses to lowercase, removing leading/trailing whitespace, or enforcing a specific format before they are saved to the database. This "Normalization" class reduces data redundancy and minimizes inconsistencies. Also, it organizes data in a structured and consistent way, making it easier to query, update, and maintain.
The Rails core team wanted to make it easy for today's and future Rails developers by providing a simple API for model attributes. All developers need to do is pass the attribute's name. Here is how they demonstrated their solution. Pow 💥
Imagine having a ClassMethod `normalizes` that comes with a set of rules, such as converting all email addresses to lowercase, removing leading/trailing whitespace, or enforcing a specific format before they are saved to the database. This "Normalization" class reduces data redundancy and minimizes inconsistencies. Also, it organizes data in a structured and consistent way, making it easier to query, update, and maintain.
The Rails core team wanted to make it easy for today's and future Rails developers by providing a simple API for model attributes. All developers need to do is pass the attribute's name. Here is how they demonstrated their solution. Pow 💥
class User < ActiveRecord::Base normalizes :email, with: -> email { email.strip.downcase } normalizes :phone, with: -> phone { phone.delete("^0-9").delete_prefix("1") } end user = User.create(email: " CRUISE-CONTROL@EXAMPLE.COM\n") user.email # => "cruise-control@example.com" user = User.find_by(email: "\tCRUISE-CONTROL@EXAMPLE.COM ") user.email # => "cruise-control@example.com" user.email_before_type_cast # => "cruise-control@example.com" User.where(email: "\tCRUISE-CONTROL@EXAMPLE.COM ").count # => 1 User.where(["email = ?", "\tCRUISE-CONTROL@EXAMPLE.COM "]).count # => 0 User.exists?(email: "\tCRUISE-CONTROL@EXAMPLE.COM ") # => true User.exists?(["email = ?", "\tCRUISE-CONTROL@EXAMPLE.COM "]) # => false User.normalize_value_for(:phone, "+1 (555) 867-5309") # => "5558675309"
Ahmed Nadar