跳至内容 跳至搜索

Active Model 错误

提供与错误相关的功能,您可以将其包含在您的对象中以处理错误消息并与 Action View 助手交互。

一个最小的实现可能是

class Person
  # Required dependency for ActiveModel::Errors
  extend ActiveModel::Naming

  def initialize
    @errors = ActiveModel::Errors.new(self)
  end

  attr_accessor :name
  attr_reader   :errors

  def validate!
    errors.add(:name, :blank, message: "cannot be nil") if name.nil?
  end

  # The following methods are needed to be minimally implemented

  def read_attribute_for_validation(attr)
    send(attr)
  end

  def self.human_attribute_name(attr, options = {})
    attr
  end

  def self.lookup_ancestors
    [self]
  end
end

最后三个方法是您的对象中必需的,以便 Errors 能够正确生成错误消息并处理多种语言。当然,如果您使用 ActiveModel::Translation 扩展您的对象,您将不需要实现最后两个方法。同样,使用 ActiveModel::Validations 将为您处理与验证相关的方法。

以上允许您执行

person = Person.new
person.validate!            # => ["cannot be nil"]
person.errors.full_messages # => ["name cannot be nil"]
# etc..
方法
#
A
C
D
E
F
G
H
I
K
M
N
O
S
T
W
包含的模块

属性

[R] errors

实际的 Error 对象数组 此方法与 objects 构成别名。

[R] objects

实际的 Error 对象数组 此方法与 objects 构成别名。

类公共方法

new(base)

传入使用错误对象的实例。

class Person
  def initialize
    @errors = ActiveModel::Errors.new(self)
  end
end
# File activemodel/lib/active_model/errors.rb, line 117
def initialize(base)
  @base = base
  @errors = []
end

实例公共方法

[](attribute)

当传入一个符号或一个方法名称时,返回该方法的错误数组。

person.errors[:name]  # => ["cannot be nil"]
person.errors['name'] # => ["cannot be nil"]
# File activemodel/lib/active_model/errors.rb, line 229
def [](attribute)
  messages_for(attribute)
end

add(attribute, type = :invalid, **options)

attribute 上添加一个新的 type 错误。可以向同一个 attribute 添加多个错误。如果没有提供 type,则假定为 :invalid

person.errors.add(:name)
# Adds <#ActiveModel::Error attribute=name, type=invalid>
person.errors.add(:name, :not_implemented, message: "must be implemented")
# Adds <#ActiveModel::Error attribute=name, type=not_implemented,
                            options={:message=>"must be implemented"}>

person.errors.messages
# => {:name=>["is invalid", "must be implemented"]}

如果 type 是一个字符串,它将用作错误消息。

如果 type 是一个符号,它将使用适当的范围进行翻译(参见 generate_message)。

person.errors.add(:name, :blank)
person.errors.messages
# => {:name=>["can't be blank"]}

person.errors.add(:name, :too_long, count: 25)
person.errors.messages
# => ["is too long (maximum is 25 characters)"]

如果 type 是一个 proc,它将被调用,允许在错误中使用诸如 Time.now 之类的东西。

如果 :strict 选项设置为 true,它将引发 ActiveModel::StrictValidationFailed 而不是添加错误。:strict 选项也可以设置为任何其他异常。

person.errors.add(:name, :invalid, strict: true)
# => ActiveModel::StrictValidationFailed: Name is invalid
person.errors.add(:name, :invalid, strict: NameIsInvalid)
# => NameIsInvalid: Name is invalid

person.errors.messages # => {}

如果错误不直接与单个属性相关联,则 attribute 应设置为 :base

person.errors.add(:base, :name_or_email_blank,
  message: "either name or email must be present")
person.errors.messages
# => {:base=>["either name or email must be present"]}
person.errors.details
# => {:base=>[{error: :name_or_email_blank}]}
# File activemodel/lib/active_model/errors.rb, line 342
def add(attribute, type = :invalid, **options)
  attribute, type, options = normalize_arguments(attribute, type, **options)
  error = Error.new(@base, attribute, type, **options)

  if exception = options[:strict]
    exception = ActiveModel::StrictValidationFailed if exception == true
    raise exception, error.full_message
  end

  @errors.append(error)

  error
end

added?(attribute, type = :invalid, options = {})

如果错误与提供的 attributetype 匹配,则返回 true,否则返回 falsetype 的处理方式与 add 相同。

person.errors.add :name, :blank
person.errors.added? :name, :blank           # => true
person.errors.added? :name, "can't be blank" # => true

如果错误需要选项,则它将使用正确的选项返回 true,或使用不正确或缺少的选项返回 false

person.errors.add :name, :too_long, count: 25
person.errors.added? :name, :too_long, count: 25                     # => true
person.errors.added? :name, "is too long (maximum is 25 characters)" # => true
person.errors.added? :name, :too_long, count: 24                     # => false
person.errors.added? :name, :too_long                                # => false
person.errors.added? :name, "is too long"                            # => false
# File activemodel/lib/active_model/errors.rb, line 372
def added?(attribute, type = :invalid, options = {})
  attribute, type, options = normalize_arguments(attribute, type, **options)

  if type.is_a? Symbol
    @errors.any? { |error|
      error.strict_match?(attribute, type, **options)
    }
  else
    messages_for(attribute).include?(type)
  end
end

as_json(options = nil)

返回一个 哈希,它可以作为此对象的 JSON 表示形式使用。您可以传递 :full_messages 选项。这决定了 JSON 对象是否应该包含完整的消息(默认情况下为 false)。

person.errors.as_json                      # => {:name=>["cannot be nil"]}
person.errors.as_json(full_messages: true) # => {:name=>["name cannot be nil"]}
# File activemodel/lib/active_model/errors.rb, line 247
def as_json(options = nil)
  to_hash(options && options[:full_messages])
end

attribute_names()

返回所有错误属性名称

person.errors.messages        # => {:name=>["cannot be nil", "must be specified"]}
person.errors.attribute_names # => [:name]
# File activemodel/lib/active_model/errors.rb, line 237
def attribute_names
  @errors.map(&:attribute).uniq.freeze
end

clear

清除所有错误。但是,清除错误不会使模型有效。下次运行验证时(例如,通过 ActiveRecord::Validations#valid?),如果任何验证失败,错误集合将再次被填充。

# File activemodel/lib/active_model/errors.rb, line 80
    

delete(attribute, type = nil, **options)

删除 key 的消息。返回已删除的消息。

person.errors[:name]        # => ["cannot be nil"]
person.errors.delete(:name) # => ["cannot be nil"]
person.errors[:name]        # => []
# File activemodel/lib/active_model/errors.rb, line 215
def delete(attribute, type = nil, **options)
  attribute, type, options = normalize_arguments(attribute, type, **options)
  matches = where(attribute, type, **options)
  matches.each do |error|
    @errors.delete(error)
  end
  matches.map(&:message).presence
end

details()

返回一个 哈希,其中包含属性与其错误详细信息的数组。

# File activemodel/lib/active_model/errors.rb, line 276
def details
  hash = group_by_attribute.transform_values do |errors|
    errors.map(&:details)
  end
  hash.default = EMPTY_ARRAY
  hash.freeze
  hash
end

each(&block)

遍历每个错误对象。

person.errors.add(:name, :too_short, count: 2)
person.errors.each do |error|
  # Will yield <#ActiveModel::Error attribute=name, type=too_short,
                                    options={:count=>3}>
end
# File activemodel/lib/active_model/errors.rb, line 67
    

empty?

如果没有错误,则返回 true。

# File activemodel/lib/active_model/errors.rb, line 90
    

full_message(attribute, message)

返回给定属性的完整消息。

person.errors.full_message(:name, 'is invalid') # => "Name is invalid"
# File activemodel/lib/active_model/errors.rb, line 451
def full_message(attribute, message)
  Error.full_message(attribute, message, @base)
end

full_messages()

以数组形式返回所有完整的错误消息。

class Person
  validates_presence_of :name, :address, :email
  validates_length_of :name, in: 5..30
end

person = Person.create(address: '123 First St.')
person.errors.full_messages
# => ["Name is too short (minimum is 5 characters)", "Name can't be blank", "Email can't be blank"]
也作为以下内容的别名: to_a
# File activemodel/lib/active_model/errors.rb, line 415
def full_messages
  @errors.map(&:full_message)
end

full_messages_for(attribute)

以数组形式返回给定属性的所有完整错误消息。

class Person
  validates_presence_of :name, :email
  validates_length_of :name, in: 5..30
end

person = Person.create()
person.errors.full_messages_for(:name)
# => ["Name is too short (minimum is 5 characters)", "Name can't be blank"]
# File activemodel/lib/active_model/errors.rb, line 430
def full_messages_for(attribute)
  where(attribute).map(&:full_message).freeze
end

generate_message(attribute, type = :invalid, options = {})

在其默认范围(activemodel.errors.messages)中翻译错误消息。

错误 消息首先在 activemodel.errors.models.MODEL.attributes.ATTRIBUTE.MESSAGE 中查找,如果在那里找不到,它将在 activemodel.errors.models.MODEL.MESSAGE 中查找,如果也找不到,它将返回默认消息的翻译(例如 activemodel.errors.messages.MESSAGE)。翻译后的模型名称、翻译后的属性名称和值可用于插值。

当在您的模型中使用继承时,它也会检查所有继承的模型,但前提是模型本身没有被找到。假设您有 class Admin < User; end 并且您想要 title 属性的 :blank 错误消息的翻译,它会查找以下翻译

  • activemodel.errors.models.admin.attributes.title.blank

  • activemodel.errors.models.admin.blank

  • activemodel.errors.models.user.attributes.title.blank

  • activemodel.errors.models.user.blank

  • 您通过 options 哈希(在 activemodel.errors 范围内)提供的任何默认值

  • activemodel.errors.messages.blank

  • errors.attributes.title.blank

  • errors.messages.blank

# File activemodel/lib/active_model/errors.rb, line 479
def generate_message(attribute, type = :invalid, options = {})
  Error.generate_message(attribute, type, @base, options)
end

group_by_attribute()

返回一个 哈希,其中包含属性与其 错误 对象的数组。

person.errors.group_by_attribute
# => {:name=>[<#ActiveModel::Error>, <#ActiveModel::Error>]}
# File activemodel/lib/active_model/errors.rb, line 289
def group_by_attribute
  @errors.group_by(&:attribute)
end

has_key?(attribute)

include? 的别名

import(error, override_options = {})

导入一个错误。导入的错误被包装为 嵌套错误,提供对原始错误对象的访问。如果需要覆盖属性或类型,请使用 override_options

选项

  • :attribute - 覆盖错误所属的属性。

  • :type - 覆盖错误类型。

# File activemodel/lib/active_model/errors.rb, line 154
def import(error, override_options = {})
  [:attribute, :type].each do |key|
    if override_options.key?(key)
      override_options[key] = override_options[key].to_sym
    end
  end
  @errors.append(NestedError.new(@base, error, override_options))
end

include?(attribute)

如果错误消息包含给定键 attribute 的错误,则返回 true,否则返回 false

person.errors.messages        # => {:name=>["cannot be nil"]}
person.errors.include?(:name) # => true
person.errors.include?(:age)  # => false
也别名为: has_key?, key?
# File activemodel/lib/active_model/errors.rb, line 202
def include?(attribute)
  @errors.any? { |error|
    error.match?(attribute.to_sym)
  }
end

key?(attribute)

include? 的别名

merge!(other)

将来自 other 的错误合并,每个 Error 都包装为 NestedError

参数

示例

person.errors.merge!(other)
# File activemodel/lib/active_model/errors.rb, line 174
def merge!(other)
  return errors if equal?(other)

  other.errors.each { |error|
    import(error)
  }
end

messages()

返回一个 Hash,其中包含属性及其错误消息数组。

# File activemodel/lib/active_model/errors.rb, line 268
def messages
  hash = to_hash
  hash.default = EMPTY_ARRAY
  hash.freeze
  hash
end

messages_for(attribute)

返回给定属性的所有错误消息,以数组形式表示。

class Person
  validates_presence_of :name, :email
  validates_length_of :name, in: 5..30
end

person = Person.create()
person.errors.messages_for(:name)
# => ["is too short (minimum is 5 characters)", "can't be blank"]
# File activemodel/lib/active_model/errors.rb, line 444
def messages_for(attribute)
  where(attribute).map(&:message)
end

of_kind?(attribute, type = :invalid)

如果属性上存在具有给定类型的错误,则返回 true,否则返回 falsetype 的处理方式与 add 相同。

person.errors.add :age
person.errors.add :name, :too_long, count: 25
person.errors.of_kind? :age                                            # => true
person.errors.of_kind? :name                                           # => false
person.errors.of_kind? :name, :too_long                                # => true
person.errors.of_kind? :name, "is too long (maximum is 25 characters)" # => true
person.errors.of_kind? :name, :not_too_long                            # => false
person.errors.of_kind? :name, "is too long"                            # => false
# File activemodel/lib/active_model/errors.rb, line 395
def of_kind?(attribute, type = :invalid)
  attribute, type = normalize_arguments(attribute, type)

  if type.is_a? Symbol
    !where(attribute, type).empty?
  else
    messages_for(attribute).include?(type)
  end
end

size

返回错误数量。

# File activemodel/lib/active_model/errors.rb, line 103
def_delegators :@errors, :each, :clear, :empty?, :size, :uniq!

to_a()

别名为: full_messages

to_hash(full_messages = false)

返回一个 Hash,其中包含属性及其错误消息。如果 full_messagestrue,它将包含完整的错误消息(参见 full_message)。

person.errors.to_hash       # => {:name=>["cannot be nil"]}
person.errors.to_hash(true) # => {:name=>["name cannot be nil"]}
# File activemodel/lib/active_model/errors.rb, line 256
def to_hash(full_messages = false)
  message_method = full_messages ? :full_message : :message
  group_by_attribute.transform_values do |errors|
    errors.map(&message_method)
  end
end

where(attribute, type = nil, **options)

搜索与 attributetypeoptions 匹配的错误。

仅匹配提供的参数。

person.errors.where(:name) # => all name errors.
person.errors.where(:name, :too_short) # => all name errors being too short
person.errors.where(:name, :too_short, minimum: 2) # => all name errors being too short and minimum is 2
# File activemodel/lib/active_model/errors.rb, line 189
def where(attribute, type = nil, **options)
  attribute, type, options = normalize_arguments(attribute, type, **options)
  @errors.select { |error|
    error.match?(attribute, type, **options)
  }
end