2013-10-23 5 views
7

条件を使用して定義された一意制約があります。しかし、次の試験に合格しない:name_changed?がfalseモンゴイ:「validates_uniqueness_of」検証は、特定のフィールドが変更されたときにのみ起動されます

class Dummy 
    include Mongoid::Document 

    field :name, :type => String 
    field :status, :type => Boolean 

    validates_uniqueness_of :name, if: :status 
end 


describe "UniquenessValidator" do 
    let!(:d1) { Dummy.create!(name: 'NAME_1', status: true) } 
    let!(:d2) { Dummy.create!(name: 'NAME_1', status: false) } 

    it "should raise an error" do 
    expect { 
     d2.status = true 
     d2.save! 
    }.to raise_error 
    end 
end 

ので、検証は起きていないようにみえので、一意性の条件はチェックされません。

バグですか?それとも私は何かを忘れてしまった?私はそれが要素が変更されるたびに検証を実行することを避けるための最適化だと思います。

この場合、ステータスが変更されたときに検証をトリガする良い方法は何ですか?

ありがとうございます!

+3

[mongoidドキュメント](http://mongoid.org Mongoidの#valid?は有効性のみを実行するのに対し、Active Recordの#valid?はすべての検証を実行します。最適化としてメモリ内にあるドキュメント」を参照してください。多分それは助けます。 –

+0

@ p11y:確かに(https://github.com/mongoid/mongoid/blob/3.1.0-stable/lib/mongoid/validations/uniqueness.rb#L289)。 hummm ... – Aymeric

+1

ダーティー回避策:モデルの上書き def attribute_changed?(attr) attr == 'name'およびself.status_changedの場合は? true else super end end – Aymeric

答えて

5

場合は、エッジケースであるあなたと、私はこのような何かが動作するはずです、このための独自のバリデータクラスを作成することをアドバイスします:

class NameUniquenessValidator < Mongoid::Validatable::UniquenessValidator 
private 
    def validation_required?(document, attribute) 
    return true "name" == attribute.to_s 
    super 
    end 
end 

class Dummy 
    include Mongoid::Document 

    field :name, :type => String 
    field :status, :type => Boolean 

    validates_with(NameUniquenessValidator, :name, if: :status) 
end 
+0

参考、私はgithubの問題を作成しました:https://github.com/mongoid/mongoid/issues/3343 – Aymeric

+0

クール..私もそれを見てみましょう。 –

1

ステータスフィールドを更新するので、このフィールドを検証する必要があります。あなたは、単一のフィールドを更新するとき、すべてのフィールドを検証するmongoidを強制することができる場合、私は知らない

class Dummy 
    include Mongoid::Document 

    field :name, :type => String 
    field :status, :type => Boolean 

    validates_uniqueness_of :name, if: :status 
    validates_uniqueness_of :status, scope: :name, if: :status 
end 

:あなたはこのような何かを行うことができます。

+0

これは正しい方向に進んでいるようですが、ステータスが一意であることを検証することは、残念ながら一般的なケースで実行可能な解決策ではありません。つまり、従属属性が一意でない場合です。 –

+0

また、最後の行に 'status'の前にコロンがありません。編集されました。 –

+0

ええ、これはこの場合の解決策です。一般的なケースでは、ステータスプロパティに応じてステータスのカスタム検証を作成する必要があります。訂正してくれてありがとう。 – drinor

関連する問題