Docs 菜单

文档验证

在本指南中,您可以学习;了解如何在 Mongoid 模型中定义验证规则。在模型中实现验证后,Mongoid 会阻止您运行违反验证规则的写入操作。 使用文档验证来限制集合中文档字段的数据类型和值范围。

Mongoid 包含 Active Record 中的 ActiveModel::Validations,用于提供验证功能,包括关联验证器和唯一性验证器。 要学习;了解更多信息,请参阅 Active Record Validations Rails指南和 ActiveModel::Validations Rails API文档。

注意

比较 Mongoid 和MongoDB验证

Mongoid 中的验证仅适用于应用程序的上下文,与在MongoDB中创建模式验证规则不同。 这意味着验证规则不适应用在应用程序外部执行的写入。 要学习;了解有关MongoDB模式验证的更多信息,请参阅服务器手册中的模式验证。

Mongoid 支持 Active Record验证助手,您可以在定义模型类时使用这些助手。 您可以使用这些助手在应用程序中设立通用验证规则,例如检查字段是否存在、将字段值与指定值进行比较或确保字段具有唯一值。

使用 validates 宏创建验证规则,然后包含验证助手和规则所需的规范。

提示

每个验证助手都接受一个或多个字段名称,这允许您为多个字段定义相同的规则。

以下代码演示了如何使用 presence验证助手来要求 Person 实例包含 name字段的值:

class Person
include Mongoid::Document
field :name, type: String
validates :name, presence: true
end

您可以在本指南的“常见验证”部分学习;了解其他有用的验证助手。

在本节中,您可以学习;了解以下常见验证规则并查看使用验证助手的示例:

您可以使用 comparison 辅助程序根据指定字段的值验证文档。

comparison 助手支持以下选项:

  • greater_than:该值必须大于提供的值。

  • greater_than_or_equal_to:该值必须大于或等于提供的值。

  • equal_to:该值必须等于提供的值。

  • less_than:该值必须小于提供的值。

  • less_than_or_equal_to:该值必须小于或等于提供的值。

  • other_than:该值必须与提供的值不同。

此示例在 Order 模型上定义了以下比较验证规则:

  • delivery_date:必须位于(大于)order_date 的值

  • quantity:必须小于 5

class Order
include Mongoid::Document
field :order_date, type: DateTime
field :delivery_date, type: DateTime
field :quantity, type: Integer
validates :delivery_date, comparison: { greater_than: :order_date }
validates :quantity, comparison: { less_than: 5 }
end

您可以使用 format 辅助程序根据字段值是否与正则表达式匹配来验证文档。 使用 with 选项指定正则表达式。

此示例在 User 模型上定义了格式验证规则,以确保 username字段仅包含字母:

class User
include Mongoid::Document
field :username, type: String
validates :username, format: { with: /\A[a-zA-Z]+\z/ }
end

提示

备用助手方法

Mongoid::Document 模块为某些验证提供了宏方法。 您可以使用 validates_format_of 方法,而不是在 validates 宏声明中使用 format验证助手,如以下代码所示:

validates_format_of :username, with: /\A[a-zA-Z]+\z/

您可以使用 inclusionexclusion 辅助程序,根据字段值是否在指定的值列表中来验证文档。 使用 in 选项指定值列表。

此示例在 Order 模型上定义包含验证规则,以确保 shipping字段值为可接受的值之一:

class Order
include Mongoid::Document
field :shipping, type: String
validates :shipping, inclusion: { in: %w(standard priority overnight) }
end

您可以使用 presenceabsence 辅助程序,根据字段值是存在还是不存在(空)来验证文档。

此示例在 Order 模型上定义了一条缺席验证规则,以确保 delivery_date字段值为 nil 或空字符串:

class Order
include Mongoid::Document
field :delivery_date, type: String
validates :delivery_date, absence: true
end

提示

备用助手方法

Mongoid::Document 模块为某些验证提供了宏方法。 您可以使用 validates_presence_of 方法,而不是在 validates 宏声明中使用 presence验证助手,如以下代码所示:

validates_presence_of :delivery_date

您可以使用 uniqueness 辅助程序,根据字段值是否不同于集合中的其他值来验证文档。 您可以使用 scope 选项指定 Mongoid 用于限制唯一性检查的一个或多个字段名称。

此示例在 Person 模型上定义了唯一性验证规则,以确保 first_name字段值在具有相同 last_name 值的文档中是唯一的:

class Person
include Mongoid::Document
field :first_name, type: String
field :last_name, type: String
validates :first_name, uniqueness: { scope: :last_name }
end

提示

备用助手方法

Mongoid::Document 模块为某些验证提供了宏方法。 您可以使用 validates_uniqueness_of 方法,而不是在 validates 宏声明中使用 uniqueness验证助手,如以下代码所示:

validates_uniqueness_of :first_name

当您在模型上使用 validates_uniqueness_of 方法时,Mongoid 会使用 primary读取偏好(read preference),因为如果它查询从节点(secondary node from replica set)集的从副本集,则可能会读取过时的数据。

此方法采用 conditions 选项,允许您指定在 Mongoid 检查唯一性时添加的条件:

validates_uniqueness_of :name, conditions: -> { where(:age.gte => 10) }

您可以使用 validates_associated 辅助程序来验证模型具有的任何关联。 当您包含此验证规则时,Mongoid 会在您每次尝试保存实例时验证任何关联文档。 要学习;了解有关关联的更多信息,请参阅 关联指南。

此示例在 Author 模型上定义了关联验证规则,以便为嵌入式 Book 实例运行验证规则:

class Author
include Mongoid::Document
embeds_many :books
validates_associated :books
end

重要

请勿在关联的两端使用 validates_associated 辅助程序,因为这会导致 Mongoid 在无限循环中执行验证。

您可以使用 validates_eachvalidates_with 辅助程序来创建自定义验证器。 要学习;了解有关这些助手的更多信息并查看示例,请参阅 Active Record 文档中的 validates_each validates_with 引用。

要学习;了解有关自定义验证器的更多信息,请参阅 Active Record 文档中的执行自定义验证。

当您将文档持久保存或保存到数据库时,Mongoid 会执行验证。 以下方法触发验证规则,因此 Mongoid 仅在对象通过验证时才会将对象保存到数据库:

  • create

  • save

  • update

当您使用上述方法的 ! 后缀版本时,如果对象验证失败,Mongoid 将返回 Mongoid::Errors::Validations 异常。

您可以使用 valid? 方法手动运行验证。 如果对象通过验证,则此方法返回 true,否则返回 false

class Person
include Mongoid::Document
field :name, type: String
field :age, type: Integer
validates :age, comparison: { greater_than_or_equal_to: 0 }
end
# Returns true
Person.new(name: "Berta Odom", age: 4).valid?
# Returns false
Person.new(name: "Cody Peng", age: -5).valid?

对持久性数据运行valid? 时,Mongoid 的行为与 Active Record 不同。 Active Record 的 valid? 会运行所有验证,但 Mongoid 的 valid? 仅对内存中的文档运行验证,以优化性能。

要进一步学习;了解可在 Mongoid 模型中使用的字段类型,请参阅 字段类型指南。

要学习;了解有关 Mongoid 中验证方法和宏的更多信息,请参阅API文档中的 Mongoid::Validatable 模块参考。

要查看 Active Record 中验证助手的完整列表,请参阅 Rails API文档中的 ActiveModel::Validations::HelperMethods 参考。