我正在尋找一個解決以下問題:我有一個由可更新的數據庫視圖通過的ActiveRecord-JDBC支持(在DB2中的ActiveRecord實體適應寶石)。該視圖包含從其他列計算出來的一列,並且是「只讀」的:您無法以任何有效方式設置該列。當爲此實體創建新記錄時,應該設置該字段而不是。但是,默認情況下,ActiveRecord會將其設置爲「默認」(NULL),該值將被數據庫拒絕。忽略「只讀」列在創建和紅寶石更新的ActiveRecord
attr_readonly是不是一個解決方案,因爲只有排除從更新一列,而不是從創建。
attr_ignore,如由「林肯寶石實現,不是解決辦法或者,因爲這時該字段被完全忽略。但是,該列仍然需要閱讀並且可以訪問。它甚至被用作關係的一部分。
有辦法阻止你設置一個ActiveRecord實體的特定屬性,但通常不會阻止包含在創建或更新語句屬性
有誰知道是否有一個辦法ActiveRecord將列指定爲'從未設置此字段'?
更新,響應Arsen7: 我已經嘗試使用after_initialize鉤從一個新創建的實體刪除屬性,因此不包括在建的SQL。這樣做的麻煩在於該屬性被完全刪除並且根本不可用,與上述「igonre_attr」情況非常相似。由於緩存,這不是微不足道的,並且需要額外的邏輯來強制重新加載這些特定表的實體。除了使用after_initialize之外,通過重寫create
來添加'重新加載'也許可以實現。
(正如Arsen7指出的,我忘了說我在ActiveRecord的3.0.9)
我的解決方案
由於我的實體已經從ActiveRecord::Base
一個子類繼承,我已經選擇添加before_create
和after_create
掛鉤。在before_create
鉤子中,我從實例的@attributes
中刪除了「計算」列。在after_create
鉤子中,我再次添加它們並從數據庫中讀取'calculated'列的值,以將它們設置爲它們接收到的值。
增加這樣的鉤子幾乎是相同的覆蓋創造,所以我認爲Arsen7的答案是正確的。
如果你想改寫「創造」,我不建議去除對象的屬性,我只是建議不指定列創建(和執行)的SQL。但觸發器呢?它看起來是最優雅的解決方案 - 您的查詢將被數據庫重寫 - 您可以從最終查詢中刪除該只讀列。 – Arsen7
我喜歡觸發器的想法,但缺點是計算字段需要在'源'字段之一更改時更新。本質上,計算的字段與其他字段上的多個觸發器相同。因此,它比多個觸發器稍微簡單一些。至於修改「創建」(也許是'更新'):我更喜歡上面修改構建SQL的方法,因爲後者更深入ActiveRecord的碗中。更高級別的更改通常更容易理解。但是,我仍然必須這樣做,而且我可能會錯誤的:) – Confusion