2014-02-25 60 views
0

場我有兩個型號,Submission(父)和SubmissionDetail(孩子)。 Submission有一個名爲status的字段,它可以是「未完成」,「待定」,「已批准」或「已拒絕」。當您創建新的Submission時,status會自動設置爲「未完成」。該孩子有一個外鍵:submission_idRuby on Rails的 - 更新父在子項創建

我想什麼發生的是創建一個新的SubmissionDetail時,其父母的狀態將自動更改爲「待定」。不知道如何去做這件事。例如,我在模型中讀了一些關於touch的內容,但我認爲這不適用於此。

回答

4

你或許可以利用ActiveRecord's callbacks更新每當創建一個新的子父。

class Submission < ActiveRecord::Base 
    has_many :submission_details 
end 

class SubmissionDetail < ActiveRecord::Base 
    belongs_to :submission 

    after_create :set_parent_to_pending 

    def set_parent_to_pending 
    # child should always have a parent, but we need to check just in case 
    submission.update(status: 'pending') unless submission.nil? 
    end 
end 

after_create回調將在子記錄創建後運行。

+0

從來不知道after_create!非常感謝,在我的項目中工作。我一定會保存你提供的鏈接。 – Rachel9494

1

Touch只是將updated_at列更新爲當前時間。你可以只添加一個after_create鉤:

class SubmissionDetail < AR 

    belongs_to :submission 
    after_create :set_pending 

    private 

    def set_pending 
    submission.update_attributes(state: "Pending") # or whatever random method 
    end 

end 
2

你當然可以通過掛鉤create來處理這個問題,但是你不會掛鉤update,某些操作不會傳播回Submission。您還在使用業務邏輯和耦合模型來拋棄持久層。

我的選擇,避免了服務對象的創建,是使用after_touch

class SubmissionDetail < ActiveRecord::Base 
    belongs_to :submission, touch: true 
end 

class Submission < ActiveRecord::Base 
    has_many :submission_details 
    after_touch :pending! 
protected 
    def pending! 
    self.status = 'pending' 
    save! 
    end 
end 

這使邏輯出SubmissionDetail並保持Submission負責保持自己的狀態保持最新。

請注意,如果你最終不得不基於流量和條件像這樣的很多操作狀態,你真的想看看積分的狀態機。

+0

我喜歡讓'Submission'負責其自己的狀態的想法,但是按照書面的說法,每次'SubmissionDetail'被改變時(不僅僅是在創建時),將會把'Submission'狀態設置爲'pending'成爲理想的行爲。如果父狀態'Submission'依賴於'SubmissionDetail'--據我所知的一些屬性'touch'回調並沒有獲得最初發射它(即'SubmissionDetail')記錄 –

+0

@carlosramireziii真。這裏沒有考慮很多邊界,這就是爲什麼我通常更願意編寫更多面向對象的代碼來處理業務邏輯並讓我的持久層專注於持久性。 Rails模型足夠了。 – coreyward

相關問題