module ActiveModel::Attributes::Normalization
def normalize_attribute(name)
User.exists?(["email = ?", "\tCRUISE-CONTROL@EXAMPLE.COM "]) # => false
User.exists?(email: "\tCRUISE-CONTROL@EXAMPLE.COM ") # => true
User.where(["email = ?", "\tCRUISE-CONTROL@EXAMPLE.COM "]).count # => 0
User.where(email: "\tCRUISE-CONTROL@EXAMPLE.COM ").count # => 1
user.email_before_type_cast # => "cruise-control@example.com"
user.email # => "cruise-control@example.com"
user = User.find_by(email: "\tCRUISE-CONTROL@EXAMPLE.COM ")
user.email # => "cruise-control@example.com"
user = User.create(email: " CRUISE-CONTROL@EXAMPLE.COM\n")
end
normalizes :phone, with: -> phone { phone.delete("^0-9").delete_prefix("1") }
normalizes :email, with: -> email { email.strip.downcase }
class User < ActiveRecord::Base
and raise +TypeError+.
Otherwise, +Marshal+ may attempt to serialize the normalization +Proc+
config.active_record.marshalling_format_version = 7.1.
higher via either config.load_defaults 7.1 or
then you should set ActiveRecord.marshalling_format_version to +7.1+ or
marshals instances of the targeted model (for example, when caching),
Be aware that if your app was created before Rails 7.1, and your app
value, or it is explicitly migrated via Normalization#normalize_attribute.
attribute will not be normalized until either it is assigned a new
record was persisted before the normalization was declared, the record's
when the attribute is fetched from the database. This means that if a
To prevent confusion, normalization will not be applied
==== Behavior with Active Record
legacy_user.email # => "cruise-control@example.com"
legacy_user.normalize_attribute(:email)
legacy_user.email # => " CRUISE-CONTROL@EXAMPLE.COM\n"
legacy_user = User.load_from_legacy_data(...)
end
normalizes :email, with: -> email { email.strip.downcase }
attribute :email, :string
include ActiveModel::Attributes::Normalization
include ActiveModel::Attributes
class User
==== Examples
Normalizes a specified attribute using its declared normalizations.
def normalize_attribute(name) # Treat the value as a new, unnormalized value. send(:"#{name}=", send(name)) end
def normalize_changed_in_place_attributes
def normalize_changed_in_place_attributes self.class.normalized_attributes.each do |name| normalize_attribute(name) if attribute_changed_in_place?(name) end end