【问题标题】:Understanding Rails validation: what does allow_blank do?了解 Rails 验证:allow_blank 有什么作用?
【发布时间】:2013-01-23 20:10:01
【问题描述】:

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

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

我对同时使用presence => trueallow_blank => true 有点困惑。

如果不使用allow_blank => true,两条规则会同时检查,不会一步步检查。

为什么allow_blank => true 会这么神奇?

【问题讨论】:

  • 在官方指南中说“:allow_blank 被存在验证器忽略。”也许这会有所帮助。

标签: ruby-on-rails


【解决方案1】:

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

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 => {...}

【讨论】:

  • 非常感谢!我刚刚在 stackoverflow 的某个地方发现了这个 sn-p,我很好奇为什么有人应该一起使用 allow_blankpresence :)
  • 例如,您可能希望将它们一起使用以显示无效格式与空白的不同错误消息。如果你不放 allow_blank 你会得到一个空白值的“无效格式”
【解决方案2】:

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

presence: true                    # nil and empty string fail validation
presence: true, allow_blank: true # nil fails validation, empty string passes

【讨论】:

  • 这是真的吗?据我了解文档,allow_blank 将跳过对所有空白值的验证。 nil 是一个空白值。对 Rails 5 的快速测试告诉我,nil 并没有通过我的验证...
  • 这个答案是超级错误的!至少在 Rails 5 中。
  • @dferrazm 在这里是正确的,您可以通过使用 allow_blank 选项查看存在验证器的测试来了解:github.com/rails/rails/blob/…
  • 一旦您在代码中验证了presenceallow_blank 如何协同工作的行为,请编辑答案并进行更正。多年前我停止使用 Rails,否则我会自己做。我依靠社区来保持这个答案是最新的和可靠的。
  • 要完成这项工作,请使用validates :columnx, presence: true, if: Proc.new{ |x| x.columnx.nil? },基于edgeguides.rubyonrails.org/…
【解决方案3】:

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

【讨论】:

    【解决方案4】:

    在您的代码中,: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" 错误(因为当电子邮件为空白时不会运行唯一性验证)。

    【讨论】:

      【解决方案5】:

      来自 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 对象仅添加一个错误,跳转唯一性验证。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-05-27
        • 2023-03-22
        • 1970-01-01
        • 1970-01-01
        • 2015-02-11
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多