2010-09-14 51 views
0

我有以下兩種模式。他們可以解釋如下:ActiveRecord關聯:如果關聯屬性匹配,則創建新的關聯或引用

報告有一個report_detail(它決定開始/結束月份)。許多報告可以具有相同的報告細節,但沒有兩個報告細節可以相同。

class Report < ActiveRecord::Base 
    # attr: name :: String 
    # attr: report_detail_id :: Integer 
    belongs_to :report_detail 
    accepts_nested_attributes_for :report_detail 
end 

class ReportDetail < ActiveRecord::Base 
    # attr: duration :: Integer 
    # attr: starting_month :: Integer 
    # attr: offset :: Integer 
end 

我有關於ReportDetail索引的唯一約束[:持續時間:starting_month,:偏移]

我試圖做到這一點是:如果一個新的報告ReportDetail有一個獨特的組合attrs(:duration,:starting_month,:offset),創建新的ReportDetail並保存爲正常。如果報告具有ReportDetail,現有的ReportDetail具有相同的屬性,請將報告的詳細信息與此ReportDetail關聯並保存報告。

我得到這個由走樣二傳手上report_detail=使用ReportDetail.find_or_create_by...工作,但它的醜陋(它也只是通過實例化與細節的屬性創建新報告創建不必要ReportDetail項,出於某種原因,我無法得到保存使用.find_or_initialize_by...正常工作)。我還在ReportDetail上嘗試了before_save來說,如果我匹配其他內容,請將self設置爲其他值。顯然你不能像這樣設置自我。

任何思考最好的方式去做這件事?

看到this gist我現在的二傳與別名

+0

你可以發佈別名代碼嗎?也許作爲一個要點,並把它連接到這裏。這聽起來像是在正確的軌道上,但可能有一兩個錯誤。加入了 – 2010-09-14 19:03:37

+0

......這段代碼沒有錯誤,它都可以工作,但我正在尋找更好的解決方案。我最大的興趣是,當你使用上面的要點進行初始化時,它實際上會創建一個ReporDetail。我也無法使它與find_or_initialize_by正常工作,因爲關聯的保存意味着在此之前發生,所以它不會最終保存關聯第一次去 – brad 2010-09-14 20:36:14

回答

1

就在這個問題今天跑覆蓋,我的解決方案是基於對object_attributes=方法,它是通過accepts_nested_attributes_for提供,我認爲這產生更少的爛攤子,而不是重寫的標準關聯設置方法。深入rails來源找到這個解決方案,這裏是github link。代碼:

class Report < ActiveRecord::Base 
    # attr: name :: String 
    # attr: report_detail_id :: Integer 
    belongs_to :report_detail 
    accepts_nested_attributes_for :report_detail 

    def report_detail_attributes=(attributes) 
    report_detail = ReportDetail.find_or_create_by_duration_and_display_duration_and_starting_month_and_period_offset(attrs[:duration],attrs[:display_duration],attrs[:starting_month],attrs[:period_offset]) 
    attributes[:id]=report_detail.id 
    assign_nested_attributes_for_one_to_one_association(:report_detail, attributes) 
    end 
end 

一些解釋,如果您提供了一個id,將被視爲更新,因此不再創建新的對象。另外我知道這種方法需要加號查詢,但目前我找不到更好的解決方案。

而且,好像你必須報告,報告的細節之間的關聯HAS_ONE,如果這是你的情況,你可以試試這個:

class Report < ActiveRecord::Base 
     # attr: name :: String 
     # attr: report_detail_id :: Integer 
     has_one :report_detail 
     accepts_nested_attributes_for :report_detail, :update_only=>true 
    end 

Accoring到documentation這應該爲你工作。 從Rails3中的文件:

:update_only

允許您指定一個現有的記錄可能只被更新。 A 只有當 沒有現有記錄時纔可以創建新記錄。此 選項僅適用於一對一 關聯,並且 集合關聯將被忽略。此選項 默認爲關閉。

希望這會有所幫助,無論如何,如果你找到更好的解決方案,請讓我知道。

+0

抱歉沒有應答/接受,我已經切換到別的東西,沒有機會測試,當我做的時候會更新,thx的答案! – brad 2010-09-30 20:46:36