跳至内容 跳至搜索
命名空间
方法
N
包含的模块

实例公共方法

normalize_attribute(name)

使用声明的规范化方法规范化指定属性。

示例

class User
  include ActiveModel::Attributes
  include ActiveModel::Attributes::Normalization

  attribute :email, :string

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

legacy_user = User.load_from_legacy_data(...)
legacy_user.email # => " CRUISE-CONTROL@EXAMPLE.COM\n"
legacy_user.normalize_attribute(:email)
legacy_user.email # => "cruise-control@example.com"

与 Active Record 的行为

为避免混淆,当从数据库获取属性时,不会应用规范化。这意味着,如果一条记录在声明规范化之前就被持久化,则该记录的属性在被分配新值或通过 Normalization#normalize_attribute 显式迁移之前,不会被规范化。

请注意,如果您的应用程序是在 Rails 7.1 之前创建的,并且您的应用程序会对其目标模型的实例进行序列化(例如,在缓存时),那么您应该通过 config.load_defaults 7.1config.active_record.marshalling_format_version = 7.1ActiveRecord.marshalling_format_version 设置为 7.1 或更高。否则,Marshal 可能会尝试序列化 Proc 规范化并引发 TypeError

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"
# File activemodel/lib/active_model/attributes/normalization.rb, line 70
def normalize_attribute(name)
  # Treat the value as a new, unnormalized value.
  send(:"#{name}=", send(name))
end