DEV Community

Cover image for Normalization in Rails 7.1 era
Ahmed Nadar
Ahmed Nadar

Posted on • Originally published at world.hey.com

3 1 1 1 1

Normalization in Rails 7.1 era

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
Enter fullscreen mode Exit fullscreen mode

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 💥

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"
Enter fullscreen mode Exit fullscreen mode

And Rails developers live happily ever after Rails 7.1 period.
The end.

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

Top comments (1)

Collapse
 
rpaweb profile image
Rafael Peña-Azar, M.Sc.Eng.

Excellent article! 👏🏼

The best way to debug slow web pages cover image

The best way to debug slow web pages

Tools like Page Speed Insights and Google Lighthouse are great for providing advice for front end performance issues. But what these tools can’t do, is evaluate performance across your entire stack of distributed services and applications.

Watch video

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay