2013-10-23 98 views
7

我有一個使用條件定義的唯一約束。但是,下面的測試不及格:Mongoid:驗證「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 

由於name_changed?是假的,沒有驗證似乎發生,因此,唯一的條件沒有被選中。

這是一個錯誤?或者我忘記了什麼?我想這是一個優化,以避免每次修改元素時都運行驗證。

在這種情況下,狀態改變時觸發驗證的好方法是什麼?

謝謝!

+3

[該mongoid文檔(http://mongoid.org /en/mongoid/docs/validation.html)指出:「當在已經存在的數據上使用#valid?時,Mongoid與Active Record的行爲略有不同.Active Record的#valid?將運行所有的驗證,而Mongoid的#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

您正在更新狀態字段,因此您需要驗證此字段。當您更新單場

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 

我不知道你是否可以強制mongoid驗證所有字段:你可以做這樣的事情。

+0

這似乎是向正確方向邁出的一步,但驗證狀態是唯一的,不幸的是在一般情況下不是可行的解決方案,即當依賴屬性不唯一時。 –

+0

此外,您在'status'之前的最後一行中缺少一個冒號。編輯。 –

+0

是的,這是這種情況下的解決方案。對於一般情況,您需要根據狀態屬性爲狀態字段創建自定義驗證。感謝您的更正。 – drinor

相關問題