Rom*_*man 61 activerecord ruby-on-rails validates-uniqueness-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
Run Code Online (Sandbox Code Playgroud)
app/models/thing.rb的内容:
class Thing < ActiveRecord::Base
validates_uniqueness_of :identification
end
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
为什么前两个创作通过?
谢谢
jdl*_*jdl 107
你错了默认行为.来自文档:
: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).
Run Code Online (Sandbox Code Playgroud)
将这两个设置为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">
Run Code Online (Sandbox Code Playgroud)
编辑:解决您的澄清问题.
添加a validates_presence_of对于您尝试执行的操作是正确的.这不是多余的,因为它正在检查完全不同的错误情况.它也有自己的错误消息,这对用户来说很重要.
class Thing < ActiveRecord::Base
validates_uniqueness_of :identification, :allow_nil => true, :allow_blank => true
validates_presence_of :identification
end
Run Code Online (Sandbox Code Playgroud)
并与validates:
validates :email, uniqueness: { allow_blank: true }
# or
validates :email, uniqueness: { allow_nil: true }
Run Code Online (Sandbox Code Playgroud)