70 votes

validates_uniqueness_of passe sur le néant ou le vide (sans allow_nil et allow_blank)

Le caractère unique du programme de validation de ActiveRecord a une options pour ignorer la validation si la valeur est nulle ou vide. Même si j'ai mis les deux paramètres à la valeur true (comportement par défaut), je peux créer un dossier avec le néant et le vide avant la validation de la frappe. J'utilise par défaut la Base de données SQlite3 sqlite3-ruby (1.2.5).

Edit pour les précisions: - je obtenir le résultat escompté si j'ajoute validates_presence_of pour le Modèle. Je pensais que le comportement par défaut de validates_uniqueness_of ferait de cette redondance.

Cas de test:

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

Le contenu des app/models/chose.rb:

class Thing < ActiveRecord::Base
  validates_uniqueness_of :identification
end

Console 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

Pourquoi les deux premières créations de passe?

Merci

122voto

jdl Points 12272

Vous vous trompez sur le comportement par défaut. À partir de la documentation:

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

Définissant à la fois de ceux de vrai, je vois le problème suivant avec 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: l'Adressage de vos éclaircissements. L'ajout d'un validates_presence_of serait correct pour ce que vous essayez de faire. Il n'est pas redondant, puisque c'est de vérifier pour un de complètement différent de l'erreur de cas. Il dispose également de son propre message d'erreur, ce qui sera important pour l'utilisateur.

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X