40

我对 Rails 很陌生,发现了一个小片段来逐步验证存在性和唯一性:首先检查存在性,然后检查唯一性。

validates :email, :presence => true, :allow_blank => true, :uniqueness => { :case_sensitive => false }

presence => true我对一起使用和有点困惑allow_blank => true

不使用allow_blank => true这两个规则将同时检查而不是一步一步。

为什么会allow_blank => true出现这种魔法?

4

5 回答 5

36

您所拥有的与此等效(为清楚起见已包装):

validates :email, :presence => true, 
            :uniqueness => { :allow_blank => true, :case_sensitive => false }

这有点愚蠢,因为如果您需要存在,那么这将使 . 的:allow_blank子句“无效” :uniqueness

当您切换到使用其他验证器时更有意义.. 说...formatuniqueness,但如果它是空白的,您不需要任何检查。在这种情况下,添加“全局应用”:allow_blank更有意义,并且 DRY 会稍微完善代码。

这...

validates :email, :format => {:allow_blank => true, ...}, 
                  :uniqueness => {:allow_blank => true, ...}

可以写成:

validates :email, :allow_blank => true, :format => {...}, :uniqueness => {...}
于 2013-01-23T21:53:03.637 回答
30

了解以下区别可能很有用:

presence: true                    # nil and empty string fail validation
presence: true, allow_blank: true # nil fails validation, empty string passes
于 2014-09-30T16:11:14.323 回答
7

:allow_blank是一个选项,它将“禁用”几个验证器,但不是存在验证器。将这两者结合使用的结果是,当该字段留空时,您将收到:blank错误消息(即“不能为空”),但不会收到其他错误消息。

于 2013-09-19T20:15:18.823 回答
4

在您的代码中,:presence =>并且:uniqueness =>是验证器,while:allow_blank =>是传递给其他验证器的默认选项。

所以你的代码:

validates(
    :email,
    :presence => true,
    :allow_blank => true,
    :uniqueness => { :case_sensitive => false }
)

相当于这段代码:

validates(
    :email,
    :presence => { :allow_blank => true },
    :uniqueness => { :allow_blank => true, :case_sensitive => false }
)

但是,presence验证器会忽略该allow_blank选项,因此您的代码最终基本上是这样的:

validates(
    :email,
    :presence => { }, # `{ }` is equivalent to `true`
    :uniqueness => { :allow_blank => true, :case_sensitive => false }
)

输入意味着当电子邮件为空白时,:allow_blank => true将不会运行验证。:uniquenessuniqueness

这样做的一个效果是您消除了数据库查询。

例如,如果没有条件,:allow_blank => true您会看到:

>> user = User.new(email: nil)
>> user.valid?
  User Exists (0.2ms) SELECT  1 AS one FROM "users" WHERE "users"."name" IS NULL LIMIT 1
=> false
>> user.errors.messages
=> {:email=>["can't be blank"]}

但是使用:allow_blank => true选项,您将不会看到User Exists数据库查询发生。

当您的数据库中已有包含空白电子邮件地址的记录时,会发生另一个极端情况的副作用。在这种情况下,如果您在验证器上没有:allow_blank => true选项uniqueness,那么您会看到返回两个错误:

>> user = User.new(email: nil)
>> user.valid?
  User Exists (0.2ms) SELECT  1 AS one FROM "users" WHERE "users"."name" IS NULL LIMIT 1
=> false
>> user.errors.messages
=> {:email=>["has already been taken", "can't be blank"]}

但是使用:allow_blank => true选项,您只会看到"can't be blank"错误(因为当电子邮件为空白时,唯一性验证不会运行)。

于 2019-05-24T15:37:45.243 回答
0

来自 Rails 注释

# * <tt>:allow_nil</tt> - Skip validation if the attribute is +nil+.
# * <tt>:allow_blank</tt> - Skip validation if the attribute is blank.

因此,这意味着当我们allow_blank在电子邮件上使用时,如果电子邮件为 nil,则仅向errors对象添加一个错误,跳转唯一性验证。

于 2017-06-07T03:37:18.463 回答