проверяет уникальность проходит на nil или пустой (без разрешить nil и разрешить пустое)


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

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

Testcase:

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

содержание приложения / модели / вещь.РБ:

class Thing < ActiveRecord::Base
  validates_uniqueness_of :identification
end

консоли рельсы:

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   51   2009-09-26 06:01:15

1 ответ:

вы ошибаетесь в поведении по умолчанию. От документы:

: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).

установив оба из них в 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: обращение к вашему разъяснению. Добавление validates_presence_of было бы правильно для того, что вы пытаетесь сделать. Это не является избыточным, так как он проверяет на совершенно другой случай ошибки. Он также имеет свое собственное сообщение об ошибке, которое будет важно для пользователь.

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