Ruby-on-rails validates_uniqueness_of 传递 nil 或空白(没有 allow_nil 和 allow_blank)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1480227/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
validates_uniqueness_of passes on nil or blank (without allow_nil and allow_blank)
提问by Roman
The uniqueness validator of ActiveRecordhas an options to skip validation if the value is nil or blank. Even if I set both parameters to true (the default behaviour) I can create one record with nil and blank before the validation hits. I use the default SQlite3 Database sqlite3-ruby (1.2.5).
如果值为 nil 或空白,ActiveRecord 的唯一性验证器有一个选项可以跳过验证。即使我将两个参数都设置为 true(默认行为),我也可以在验证命中之前创建一个带有 nil 和空白的记录。我使用默认的 SQlite3 数据库 sqlite3-ruby (1.2.5)。
Edit for clarification: I get the expected result if I add validates_presence_ofto the Model. I thought that the default behaviour of validates_uniqueness_ofwould make this redundant.
编辑澄清:如果我添加validates_presence_of到模型,我会得到预期的结果。我认为 的默认行为validates_uniqueness_of会使这变得多余。
Testcase:
测试用例:
rails validation_test
cd validation_test/
script/generate Model Thing identification:string
rake db:migrate
Content of app/models/thing.rb:
app/models/thing.rb 的内容:
class Thing < ActiveRecord::Base
validates_uniqueness_of :identification
end
Rails console:
导轨控制台:
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
Why do the first two creations pass?
为什么前两个创作会通过?
Thanks
谢谢
回答by jdl
You are mistaken about the default behavior. From the docs:
您误解了默认行为。从文档:
:allow_nil - If set to true, skips this validation if the attribute is nil (default is false).
:allow_blank - If set to true, skips this validation if the attribute is blank (default is false).
Setting both of those to true, I see the following behavior with Rails 2.3.4.
将这两个设置为 true,我看到 Rails 2.3.4 的以下行为。
class Thing < ActiveRecord::Base
validates_uniqueness_of :identification, :allow_blank => true, :allow_nil => 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">
Edit: Addressing your clarification.Adding a validates_presence_ofwould be correct for what you're trying to do. It's not redundant, since it's checking for a completely different error case. It also has its own error message, which will be important for the user.
编辑:解决您的澄清。添加 avalidates_presence_of对于您要执行的操作是正确的。这不是多余的,因为它正在检查完全不同的错误情况。它也有自己的错误消息,这对用户很重要。
class Thing < ActiveRecord::Base
validates_uniqueness_of :identification, :allow_nil => true, :allow_blank => true
validates_presence_of :identification
end

