2009-06-17 106 views
2

更具體地說,「如何驗證模型是否至少需要創建x個有效的關聯模型?」。我一直在嘗試驗證嵌套模型,它們是以與父代相同的形式創建的(並最終顯示立即驗證la jQuery)。作爲一個流行的例子,讓我們假設以下模型和模式。驗證嵌套模型?

class Project 
    include DataMapper::Resource 

    property :id,  Serial 
    property :title, String, :nullable => false 

    has 2..n, :tasks 
end 

class Task 
    include DataMapper::Resource 

    property :id,   Serial 
    property :project_id, Integer, :key => true 
    property :title,  String, :nullable => false 

    belongs_to :project 
end 

所有驗證都在模式定義中完成,如您所見。這裏最重要的是「has 2..n, :tasks」。考慮到params散列中的嵌套任務屬性將產生有效的任務,此驗證實際上正常工作。但是,如果他們產生了無效的任務,那麼該任務將不會被創建,並且最終會得到一個項目少於2個任務,因此會產生項目對象無效的

據我所知,這是因爲它不能確定任務屬性是否有效,直到它試圖保存任務,並且因爲 - 據我所知 - 任務不能在項目之前得到保存,項目不知道這些任務是否有效。我認爲這是否正確?

無論如何,我希望能有一個快速的答案,但似乎沒有那麼微不足道,我希望。如果你有任何建議,那將不勝感激。

回答

2

我實際上在DataMapper中使用事務找到了一個很好的解決方案。基本上這個事務試圖保存父對象以及所有的子對象。一旦保存失敗,交易就會停止,並且不會創建任何內容。如果一切順利,則對象將成功保存。

class Project 
    def make 
    transaction do |trans| 
     trans.rollback unless save 
     tasks.each do |task| 
     unless task.save 
      trans.rollback 
      break 
     end 
     end 
    end 
    end 
end 

這可以確保在任何事情得到保存之前,一切都是有效的。我只需要將我的#save和#update方法更改爲#在我的控制器代碼中生成。

0

如果您的數據庫引擎支持SET CONSTRAINTS DEFERRED可能會很有用。

否則,也許編寫一個存儲過程來執行插入操作,然後說它的存儲過程的可靠性,以確保只插入正確的,經過驗證的數據。

+0

感謝克里斯,這些都是很好的建議,雖然我不是在尋找特定於數據庫的解決方案。我希望邏輯和驗證保持在應用程序本身內。如果最差的情況最糟糕,我只會寫一個保存後鉤來驗證記錄(醜陋,我知道,但可能是唯一明智的方法)。 – 2009-06-18 20:34:28

0

有一個模型方法valid?在模型對象保存之前運行驗證。因此,驗證關聯的簡單方法是使用validates_with_block' or 'validates_with_method來檢查關聯上的驗證。

這將是這個樣子

validates_with_block do 
    if @tasks.all?{|t|t.valid?} 
    true 
    else 
    [false, "you have an invalid task"] 
    end 
end 

或者你可以看看dm-association-validatordm-accepts-nested-attributes

編輯:額外的瘋狂。對任務運行驗證,然後檢查唯一的錯誤是否與關聯有關。

validates_with_block do 
    if @tasks.all?{|t|t.valid?;!t.errors.any?{|e|e[0]==:project}} 
    true 
    else 
    [false, "you have an invalid task"] 
    end 
end 
+0

不幸的是,所有任務在那時都是無效的,因爲它們還沒有被保存(ID => nil,project_id => nil等),所以驗證總是返回false。這是問題所在,因爲父AND子項同時以相同的形式創建。 – 2009-06-21 07:56:16

+0

我也試過沒有運氣的dm-accep_nested_attributes。我在IRC與snusnu(插件作者)聊過,似乎無法弄清楚。這是一個已知的問題,但似乎是一個灰色地帶。 – 2009-06-21 08:06:16