2009-09-26 9 views
49

The uniqueness validator of ActiveRecordには、値がnilまたは空白の場合は検証をスキップするオプションがあります。両方のパラメータをtrue(デフォルトの動作)に設定しても、検証ヒットの前にnilと空白のレコードを作成できます。私はデフォルトのSQlite3データベースsqlite3-ruby(1.2.5)を使用します。validates_uniqueness_ofがnilまたはblank(allow_nilおよびallow_blankなし)に渡す場合

説明のために編集:validates_presence_ofをモデルに追加すると、予想通りの結果が得られます。私はvalidates_uniqueness_ofのデフォルトの動作がこれを冗長にすると考えました。

テストケース:アプリ/モデル/ thing.rbの

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

内容:

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 

なぜ最初の2点の作品が通過していますか?

ありがとうございました

+1

+1これは質問する方法のモデルですので、あなたは、あなたが何をしたか、あなたが見たもの、そしてあなたが期待したものを明確に述べました。 – jdl

+0

ありがとうございます。しかし、これは誤解されることを防ぐものではないようです。 :) – Roman

答えて

89

あなたはデフォルトの動作について誤解されています。 the docsから:trueにそれらの両方を設定

: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を追加すると、あなたがしようとしているものが正しいでしょう。まったく異なるエラーケースをチェックしているので、冗長ではありません。また、独自のエラーメッセージが表示されます。これはユーザーにとって重要なものです。

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

実際に私はそれを逆にしたい。私はゼロと空白の値を完全に防ぎたい。追加validates_presence_ofのようにします。しかし、validates_uniqueness_ofバリデータがすでに存在する場合、validates_presenceは冗長になると思いました。 – Roman

+0

さて、これは理にかなっています。実際にはnullでも空白でも一意にすることができます。私が空の値を避けたいのであれば、私はこれを明示的に言わなければなりません。 まず、私はそれが刺激的であることが分かった。今、もう一度考えると、私はそれをもっと好きにしています。私はちょうど正しい方向への私の考えを別の非常に小さな一歩を得たと思う。ありがとう。 – Roman

+9

':allow_blank => true'にはnil値が含まれます。したがって、追加の:allow_nil => trueは冗長です。 – wdspkr