Подтвердить что ты не робот

Validates_uniqueness_of проходит по нуле или пробелу (без allow_nil и allow_blank)

Валидатор уникальности ActiveRecord имеет параметры пропуска проверки, если значение равно нулю или пусто. Даже если я установил оба параметра в 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

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

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

Спасибо

4b9b3361

Ответ 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">

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

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