Ruby on rails 理解Rails验证:什么是允许的?
我是Rails的新手,找到了一个小片段来逐步验证存在性和唯一性:首先检查存在性,然后检查唯一性Ruby on rails 理解Rails验证:什么是允许的?,ruby-on-rails,Ruby On Rails,我是Rails的新手,找到了一个小片段来逐步验证存在性和唯一性:首先检查存在性,然后检查唯一性 validates :email, :presence => true, :allow_blank => true, :uniqueness => { :case_sensitive => false } 我对同时使用presence=>true和allow\u blank=>true感到有点困惑 如果不使用allow\u blank=>true将同时检查这两个规则,而不是逐
validates :email, :presence => true, :allow_blank => true, :uniqueness => { :case_sensitive => false }
我对同时使用presence=>true
和allow\u blank=>true
感到有点困惑
如果不使用allow\u blank=>true
将同时检查这两个规则,而不是逐步检查
为什么
allow\u blank=>true
会产生这种魔力?您所得到的与此等价(为了清晰起见包装):
这有点傻,因为如果你需要在场,那么这将使:allow_blank子句对:university“无效”
validates :email, :presence => true, :allow_blank => true, :uniqueness => { :case_sensitive => false }
当您切换到使用其他验证器时,它更有意义。。说。。。格式和唯一性,但如果为空,则不需要任何检查。在这种情况下,添加一个“全局应用”:allow_blank更有意义,并使代码干涸一点
这个
validates :email, :format => {:allow_blank => true, ...},
:uniqueness => {:allow_blank => true, ...}
可以这样写:
validates :email, :allow_blank => true, :format => {...}, :uniqueness => {...}
:allow_blank
是一个选项,它将“禁用”多个验证器,但不会禁用状态验证器。将这两个字段一起使用的结果是,当字段留空时,您将得到:blank
错误消息(即“不能为空”),但不会得到其他错误消息。了解以下区别非常有用:
presence: true # nil and empty string fail validation
presence: true, allow_blank: true # nil fails validation, empty string passes
来自Rails注释
\*:allow#nil-如果属性为+nil+,则跳过验证。
#*:allow_blank-如果属性为空,则跳过验证。
因此,这意味着当我们在电子邮件上使用
允许空白
时,如果电子邮件为零,则只有一个错误添加到errors
对象中,跳转唯一性验证。在您的代码中,:presence=>
和:university=>
是验证程序,而:allow_blank=>
是传递给其他验证器的默认选项
因此,您的代码:
验证(
:电邮,
:presence=>true,
:allow_blank=>true,
:唯一性=>{:区分大小写=>false}
)
等同于此代码:
验证(
:电邮,
:presence=>{:allow_blank=>true},
:university=>{:allow_blank=>true,:区分大小写=>false}
)
但是,presence
验证器忽略了allow\u blank
选项,因此您的代码基本上是这样的:
验证(
:电邮,
:presence=>{},#`{}`等同于'true'`
:university=>{:allow_blank=>true,:区分大小写=>false}
)
在:university
中具有:allow_blank=>true
意味着当电子邮件为空时,university
验证将不会运行
这样做的一个效果是消除了DB查询
例如,如果没有: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
选项,您将不会看到用户存在
数据库查询发生
当您的数据库中已有一个电子邮件地址为空的记录时,会发生另一种边缘情况的副作用。在这种情况下,如果您没有唯一性
验证器上的: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”
错误(因为当电子邮件为空时,唯一性验证将不会运行)。在官方指南中说:“allow_blank被状态验证程序忽略”。这可能会有所帮助。另外,请查看一下,谢谢!我刚刚在stackoverflow上的某个地方发现了这段代码,并开始好奇为什么有人应该一起使用allow_blank
和presence
:)例如,您可能想一起使用它们来显示无效格式与空白格式的不同错误消息。如果不将allow_设置为空,则会得到一个空值的“无效格式”,这是真的吗?据我所知,allow_blank将跳过对所有空白值的验证nil
为空值。Rails 5上的一个快速测试告诉我,nil
不会使我的验证失败……这个答案是非常错误的!至少在Rails 5中。@dferrazm在这里是正确的,您可以通过查看带有allow_blank
选项的状态验证程序的测试来查看:在代码中验证了presence
和allow_blank
如何协同工作的行为后,请编辑带有更正的答案。很多年前我就停止使用Rails了,否则我会自己做。我依靠社区来保持此答案的最新性和可靠性。要使此工作正常,请使用validates:columnx,presence:true,if:Proc.new{x | x.columnx.nil}
,基于
>> 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"]}