一些背景:活動記錄,使用實例變量在before_destroy塊定義
一個公司有很多用戶。誰是主人。 您可以銷燬除所有者以外的所有公司。 摧毀業主,就像摧毀公司。所以你必須做company.destroy
我防止銷燬用戶,如果他是所有者,除非你正在銷燬公司。
我的代碼:
class Company < ActiveRecord::Base
before_destroy { @bool_allow_owner_be_destroyed = true ; p object_id }
belongs_to :owner, class_name: 'User', foreign_key: 'owner_id'
has_many :employees, class_name: 'User', dependent: :destroy
def can_owner_be_destroyed?
p @bool_allow_owner_be_destroyed
p object_id
[email protected]_allow_owner_be_destroyed
end
end
class User < ActiveRecord::Base
belongs_to :company
before_destroy :cancel_if_owner
def cancel_if_owner
!self.is_owner? || self.company.can_owner_be_destroyed?
end
end
我的問題:
當我打電話company.destroy
我看到我的調試。我通過before_destroy { @bool_allow_owner_be_destroyed = true ; p object_id }
,我看到了我的object_id。 當我通過can_owner_be_destroyed?
方法時,我有相同的object_id,但我的@bool_allow_owner_be_destroyed
是nil
。這是我的代碼中唯一的地方,我觸摸了@bool_allow_owner_be_destroyed
變量。
任何想法?
感謝您的非常詳細的答案。 但我不同意你的看法。你說「before_destroy回調爲父對象運行」,但我認爲這取決於你的聲明的順序。 在你的例子中,你已經改變了聲明的順序 – djothefou
我認爲執行順序對我們兩個人都不明顯的事實是足夠的理由,不要依賴回調來做這件事,不是嗎? :)回調功能強大,但對於可通過內置語言功能實現的功能也可能過於複雜。你也不能在回調中拋出像'destroy'這樣的動作。我認爲使用Ruby的內置回調系統(即'super')更適合你。你可以精確地控制它的執行時間,並且能夠早於你的'destroy'方法返回,與回調不同。 Ruby的強大,應該用它! –
我也仍然不認爲你應該依賴一個實例變量來承載這個狀態。我不會假設我知道什麼時候一個新的對象將會或者不會像這樣在一個很長的執行流中被實例化,消除你的實例變量。不妨一次額外打一次數據庫以保證對象狀態的完整性 –