【问题标题】:validates_uniqueness_of passes on nil or blank (without allow_nil and allow_blank)validates_uniqueness_of 传递 nil 或空白(没有 allow_nil 和 allow_blank)
【发布时间】:2009-09-26 02:01:15
【问题描述】:

The uniqueness validator of ActiveRecord 可以选择在值为 nil 或空白时跳过验证。即使我将两个参数都设置为 true (默认行为),我也可以在验证命中之前创建一个带有 nil 和空白的记录。我使用默认的 SQlite3 数据库 sqlite3-ruby (1.2.5)。

编辑澄清:如果我将validates_presence_of 添加到模型中,我会得到预期的结果。我认为validates_uniqueness_of 的默认行为会使这变得多余。

测试用例:

rails validation_test
cd validation_test/
script/generate Model Thing identification:string
rake db:migrate

app/models/thing.rb 的内容:

class Thing < ActiveRecord::Base
  validates_uniqueness_of :identification
end

Rails 控制台:

script/console 
Loading development environment (Rails 2.3.4)
>> Thing.create!
=> #<Thing id: 1, identification: nil, created_at: "2009-09-26 01:49:32", updated_at: "2009-09-26 01:49:32">
>> Thing.create! :identification => ""
=> #<Thing id: 2, identification: "", created_at: "2009-09-26 01:49:42", updated_at: "2009-09-26 01:49:42">
>> Thing.create! :identification => ""
ActiveRecord::RecordInvalid: Validation failed: Identification has already been taken
    from /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/validations.rb:1090:in `save_without_dirty!'
    from /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/dirty.rb:87:in `save_without_transactions!'
    from /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/transactions.rb:200:in `save!'
    from /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/connection_adapters/abstract/database_statements.rb:136:in `transaction'
    from /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/transactions.rb:182:in `transaction'
    from /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/transactions.rb:200:in `save!'
    from /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/transactions.rb:208:in `rollback_active_record_state!'
    from /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/transactions.rb:200:in `save!'
    from /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/validations.rb:1059:in `create!'
    from (irb):3
>> Thing.count
=> 2

为什么前两个创造通过了?

谢谢

【问题讨论】:

  • +1 因为这是一个如何提问的模型。你清楚地说明了你做了什么,你看到了什么,你期望什么。
  • 谢谢。但这似乎并不能防止被误解。 :)

标签: ruby-on-rails activerecord validates-uniqueness-of


【解决方案1】:

您对默认行为有误。来自the docs

:allow_nil - 如果设置为 true,则在属性为 nil 时跳过此验证(默认为 false)。 :allow_blank - 如果设置为 true,则在属性为空时跳过此验证(默认为 false,it includes nil too)。

allow_blank 设置为 true,我看到 Rails 2.3.4 出现以下行为。

class Thing < ActiveRecord::Base
  validates_uniqueness_of :identification, :allow_blank => true
end

>> Thing.create! :identification => ""
=> #<Thing id: 6, identification: "", created_at: "2009-09-26 03:09:48", updated_at: "2009-09-26 03:09:48">
>> Thing.create! :identification => ""
=> #<Thing id: 7, identification: "", created_at: "2009-09-26 03:09:49", updated_at: "2009-09-26 03:09:49">
>> Thing.create! :identification => nil
=> #<Thing id: 8, identification: nil, created_at: "2009-09-26 03:09:52", updated_at: "2009-09-26 03:09:52">
>> Thing.create! :identification => nil
=> #<Thing id: 9, identification: nil, created_at: "2009-09-26 03:09:53", updated_at: "2009-09-26 03:09:53">

编辑:解决您的说明。

添加validates_presence_of 对您要执行的操作是正确的。这不是多余的,因为它正在检查一个完全不同的错误情况。它还有自己的错误消息,这对用户来说很重要。

class Thing < ActiveRecord::Base
  validates_uniqueness_of :identification, :allow_blank => true
  validates_presence_of :identification
end

【讨论】:

  • 其实我想反过来。我想完全防止 nil 和空白值。就像额外的 validates_presence_of 一样。但是我认为如果已经有一个 validates_uniqueness_of 验证器,那么 validates_presence 将是多余的。
  • 好吧,这很有意义。实际上,即使是空和空白也可以是唯一的。如果我想防止空值,我必须明确地说出来。首先我发现它很烦人。现在,再想一想,我什至更喜欢这种方式。我想我只是让我的想法朝着正确的方向迈出了一小步。谢谢。
  • :allow_blank =&gt; true 包含 nil 值。所以额外的:allow_nil =&gt; true 是多余的。
【解决方案2】:

validates:

validates :email, uniqueness: { allow_blank: true }
# or
validates :email, uniqueness: { allow_nil: true }

【讨论】:

    【解决方案3】:
    class Thing < ActiveRecord::Base
      validates :identification, uniqueness: true, allow_nil: true
    end
    

    【讨论】:

    • 虽然此代码可能会回答问题,但提供有关 why 和/或 如何 此代码回答问题的附加上下文可提高其长期价值.
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-03
    • 1970-01-01
    • 2022-12-26
    • 2020-08-15
    相关资源
    最近更新 更多