2009-09-26 2 views
49

The uniqueness validator of ActiveRecord имеет возможность пропустить проверку, если значение равно нулю или пусто. Даже если я установил оба параметра в true (поведение по умолчанию), я могу создать одну запись с нулем и пробелом до того, как будут проверены проверки. Я использую базу данных SQlite3 по умолчанию sqlite3-ruby (1.2.5).validates_uniqueness_of проходит по нуле или пробелу (без allow_nil и allow_blank)

Редактировать для уточнения: Я получаю ожидаемый результат, если я добавлю validates_presence_of в Модель. Я думал, что поведение по умолчанию validates_uniqueness_of сделает это избыточным.

TestCase:

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

Содержание приложения/модели/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 

Почему первые два творения проходят?

Thanks

+1

+1 потому что это модель, как задать вопрос. Вы четко заявили, что вы сделали, что видели, и что вы ожидали. – jdl

+0

Спасибо. Но похоже, что это не мешает быть неправильно понятым. :) – Roman

ответ

89

Вы ошибаетесь в отношении поведения по умолчанию. От 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). 

Установка и тех, истинно, я вижу следующее поведение с 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"> 

Редактировать: Обращение с разъяснением. Добавление validates_presence_of будет правильным для того, что вы пытаетесь сделать. Это не избыточно, поскольку он проверяет совершенно другой случай ошибки. Он также имеет собственное сообщение об ошибке, которое будет важно для пользователя.

+0

На самом деле, я хочу, чтобы все было наоборот. Я хочу полностью исключить нулевые и пустые значения. Как и дополнительная validates_presence_of. Но я думал, что validates_presence будет избыточным, если уже есть validates_uniqueness_of validator. – Roman

+0

Теперь это имеет смысл. Даже пустая и пустая на самом деле может быть уникальной. Если я хочу предотвратить пустые значения, я должен прямо сказать это. Сначала я нашел это раздражающим. Теперь, со второй мыслью, мне даже нравится больше. Кажется, я просто подумал о другом очень маленьком шаге в правильном направлении. Благодарю. – Roman

+9

': allow_blank => true' включает значения nil. Таким образом, дополнительный ': allow_nil => true' является избыточным. – wdspkr

Смежные вопросы