在您的代码中,:presence => 和 :uniqueness => 是验证器,而 :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 }
)
:uniqueness 中有:allow_blank => true 表示当电子邮件为空白时,uniqueness 验证将不会运行。
这样做的一个效果是您消除了数据库查询。
例如,没有 :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 DB 查询发生。
当您在数据库中拥有一条带有空白电子邮件地址的记录时,会发生另一个极端情况的副作用。在这种情况下,如果您没有在uniqueness 验证器上具有: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=>["has already been taken", "can't be blank"]}
但是使用:allow_blank => true 选项,您只会看到"can't be blank" 错误(因为当电子邮件为空白时不会运行唯一性验证)。