2010-11-21 125 views
10

我有一個應用程序,我想重寫銷燬我的許多模型的行爲。用例是用戶可能有合理需要刪除特定記錄,但實際上從數據庫中刪除該行將會破壞影響其他相關模型的參照完整性。例如,系統的用戶可能想要刪除不再經營業務的客戶,但需要維護與該客戶的交易。重寫Rails ActiveRecord銷燬行爲的最佳方式是什麼?

看來我至少有兩個選項:

  1. 複製數據到一定的模型有效反規範化我的數據模型,使刪除的記錄不會影響相關的數據。
  2. 重寫ActiveRecord的「銷燬」行爲來設置一個標誌,指示用戶「刪除」了該記錄並使用此標誌隱藏記錄。

我錯過了一個更好的方法嗎?

選項1對我來說似乎是一個可怕的想法,儘管我很樂意聽到相反的論點。

選項2似乎有點Rails-ish,但我想知道處理它的最佳方法。我是否應該創建自己的繼承自ActiveRecord :: Base的父類,並覆蓋那裏的destroy方法,然後從我想要這種行爲的模型中繼承那個類?我是否也應該重寫查找器行爲,以便標記爲已刪除的記錄不會被默認返回?

如果我這樣做,我將如何處理動態查找器?什麼命名範圍?

回答

8

如果你不是再次見到這些記錄真正感興趣的,但只關心孩子仍然存在當父被破壞,工作也很簡單:添加:dependent => :nullifyhas_many調用引用設置的母體NULL自動銷燬後,教導視圖以處理丟失的參考。但是,如果您沒有再次查看該行,即可查看這些交易,則在公司名稱下顯示「[NO LONGER EXISTS]」,此操作纔有效。

如果不想再看到這些數據,這聽起來像你想要什麼無關,與實際破壞記錄,這意味着你將永遠不需要再次提及他們。隱藏似乎是要走的路。正如你所建議的那樣,由於你沒有實際銷燬記錄,所以將你的行爲放在hide方法中會觸發一個標誌,而不是重寫摧毀,而不是重寫摧毀記錄。

從那裏,無論何時您想要列出這些記錄並只包含可見記錄,一個簡單的解決方案就是包含一個不包含隱藏記錄的範圍,並且在您想要查找特定隱藏記錄時不包含它再次錄製。另一種方法是使用default_scope來隱藏隱藏的記錄,並使用Model.with_exclusive_scope { find(id) }來提取隱藏的記錄,但是我建議不要這樣做,因爲它可能對於新來的開發者來說是一個嚴重的問題,並且從根本上改變了Model.all返回到根本不變的狀態反映方法調用建議的內容。

我的理解,使控制器看起來像他們正在做的事情Rails的方式的願望,但是當你不真的做事Rails的方式,最好要明確一下,尤其是當它是真的這樣做並不是那麼痛苦。

+0

感謝Matchu。你是對的,我需要再次使用這些數據,所以無效不是我正在尋找的。雖然Ryan的插件在他的回答中提到的簡單性很有吸引力,但你對這種行爲的明確說服的說法使我相信。我很欣賞這種迴應。 – 2010-11-21 15:20:40

6

我寫了a plugin for this exact purpose,叫做偏執狂。我從acts_as_paranoid「借用」了這個想法,並且使用更少的代碼重新編寫了AAP。

當您在記錄上調用destroy時,它實際上並未將其刪除。相反,它會將數據庫中的deleted_at列設置爲當前時間。

GitHub頁面上的README應該對安裝&的用法有所幫助。如果不是,那麼讓我知道,我會看看我能否爲你解決這個問題。

相關問題