2010-03-10 38 views
2

我有以下一對多關聯。文檔有很多部分,部分有很多項目。Rails自動保存控制器操作中的關聯

class Document < ActiveRecord::Base 
    has_many :document_sections, :dependent => :destroy, :autosave => true 
    has_many :document_items, :through => :document_sections 
end 

class DocumentSection < ActiveRecord::Base 
    belongs_to :document 
    has_many :document_items, :dependent => :destroy, :autosave => true 
end 

class DocumentItem < ActiveRecord::Base 
    belongs_to :document_section 
end 

這裏是params哈希表:

- 
Parameters: {"commit"=>"Submit Document", "authenticity_token"=>"4nx2B0pJkvavDmkEQ305ABHy+h5R4bZTrmHUv1setnc=", "id"=>"10184", "document"=>{"section"=>{"10254"=>{"seqnum"=>"3", "item"=>{"10259"=>{"comments"=>"tada"}}}}, "comment"=>"blah"}} 

我有以下的更新方法...

# PUT /documents/1                                     
# PUT /documents/1.xml 




def update 
    @document = Document.find(params[:id]) 

    # This is header comment 
    @document.comment = params[:document][:comment] 

    params[:document][:section].each do |k,v| 
     document_section = @document.document_sections.find_by_id(k) 
     if document_section 

      v[:item].each do |key, value| 
      document_item = document_section.feedback_items.find_by_id(key) 
      if document_item 

       # This is item comments 
       document_item.comments = value[:comments] 
      end 
      end 

     end 
    end 

    @document.save 

    end 

當我保存它僅更新文檔標題註釋的文檔。它不保存document_item註釋。不應該自動保存選項也更新關聯。

在日誌中只有以下DML註冊:

UPDATE documents SET updated_at = TO_DATE('2010-03-09 08:35:59','YYYY-MM-DD HH24:MI:SS'), comment = 'blah' WHERE id = 10184 

如何通過保存文檔保存的關聯。

+1

如果你不介意,請清理你的文章格式。我錯讀了一半。您突出顯示代碼位,然後單擊代碼按鈕以正確縮進(4個空格)。在你的例子中,最好爲每個「文件」創建一個單獨的代碼塊。 – dpb 2010-03-10 06:47:32

+0

@dpb同意。我修改了一下佈局,但@ ash34請嘗試使用語法高亮等來改進它。這個問題幾乎不可讀 – marcgg 2010-03-10 11:19:39

回答

2

我想我明白了問題所在。我敢肯定,你不能做到以下幾點:

# Triggers a database call 
document_section = @document.document_sections.find_by_id(k) 

,並期望ActiveRecord的保持協會自動保存。相反,您應該單獨保存加載的記錄。當然不會是原子的。

我相信自動保存到像你所想的工作,你想要做這樣的事:不要叫find_by_id

# untested... 
@document.document_sections.collect { |s| s.id == k }.foo = "bar" 

請注意,我在這裏居然在陣列中修改一個假PARAM foo, ,它將重新查詢數據庫並返回一個新的對象。

您擁有的第三個選項是,您當然可以按照您原先的計劃進行操作,但自己處理所有事務,或使用嵌套事務等來獲取atmoic保存。如果你的數據太大,數組操作無法工作,這將是必要的,因爲它的自性保存會觸發所有相關數據加載到內存中。

這一切都取決於您的應用程序。


底層問題的一些澄清:

如果運行find_by_id方法,你問ActiveRecord返回到你一套新的匹配查詢的對象。已執行從一個實例(document_sections)這種方法其實是真正要說的只是另一種方式:

DocumentSection.find_by_id(k) 

從一個對象實例我想調用它只是一些語法美好的事物是Rails是增加對事物的頂部,但在我看來,這並沒有多大意義。我認爲它在某些應用中可能很方便,我不確定。

另一方面,collect是一種Ruby Array方法,它提供了一種使用塊「切片」數組的方法。基本上是一個花哨的foreach循環。:)通過直接與document_sections數組進行交互,您將更改已加載到包含對象(@document)中的相同對象,然後在save設置了特殊autosave標誌時將其提交。

HTH!很高興你回來並跑步。 :)

+0

模型從主題的第二行開始發佈。我知道'accep_nested_attributes_for'。由於我沒有使用批量分配,因此我希望這可以在不存在'accept_nested_attributes_for'選項的情況下保存。 – user290870 2010-03-10 06:35:52

+0

我重新讀你的問題,並調整我的答案。讓我知道這是否有幫助。 – dpb 2010-03-10 07:17:28

+0

格式化的抱歉。非常感謝答覆。採用'collect'方法的未經檢驗的解決方案正常工作!我有點明白你在說什麼。在你的評論中你提到「將重新查詢數據庫並返回一個新對象」。我的印象是,自動保存和數據庫查詢加載的對象都返回對同一對象的引用(表中同一底層行),使用哪個對象引用來修改對象並不重要。你能澄清這個基本概念嗎?再次感謝。 – user290870 2010-03-10 20:03:51