2014-03-27 63 views
1

我正在使用Rails 3.2.16。在我的應用程序中,有一個帳戶has_many用戶。一個帳戶必須始終有管理員用戶,所以你不能銷燬它們。這需要照顧:Rails ActiveRecord 3.2:如何在子模型中跳過before_delete回調?

class Account < ActiveRecord::Base 
    has_many :users, :dependent => :destroy 
end 

class User < ActiveRecord::Base 
    before_destroy :check_if_admin 

    def check_if_admin 
    false if self.is_admin 
    end 
end 

但是,當你銷燬整個帳戶時,管理員也應該銷燬。相反,當我從控制器呼叫@account.destroy時,User#before_delete回調可防止管理員用戶被破壞。

我知道我可以撥打@account.delete跳過回調,但我的理解是:dependent => :destroy本身就是一個回調,所以只會刪除帳戶,而不是用戶。

回調中有沒有方法可以知道我從哪裏來,例如

def check_if_admin 
    return if [I'm doing an Account dependent delete] 
    false if self.is_admin 
end 

還是我不得不手動deletedestroy之前,荷蘭國際集團的用戶帳戶?

回答

2

this answer的幫助下,我找到了這個解決方案。這個想法是暫時關閉特定的小孩回調,同時摧毀父母。請注意,我必須添加:prepend => :true選項才能將自定義回調重新添加到鏈條的前端。

class Account < ActiveRecord::Base 
    before_destroy :disable_user_check_if_admin 
    before_destroy :enable_user_check_if_admin 

    has_many :users, :dependent => :destroy 

    def disable_user_check_if_admin 
    User.skip_callback(:destroy, :before, :check_if_admin) 
    end 

    def enable_user_check_if_admin 
    User.set_callback(:destroy, :before, :check_if_admin), :prepend => :true 
    end 
end 

class User < ActiveRecord::Base 
    before_destroy :check_if_admin 
    has_many :contacts, :dependent => :restrict 

    def check_if_admin 
    false if self.is_admin 
    end 
end 

沒有:prepend => :true,我遇到了麻煩,因爲我的用戶模型也has_many :contacts, :dependent => :restrict。問題是,skip_callback實際上刪除了回調,並且set_callback在回調鏈的末尾重新添加了回調。使用:prepend => :true,我能夠將我自定義的before_destroy :check_if_admin回調插入鏈條的前端。請參閱文檔和源代碼here

替代解決方案(未使用)

雖然我打回調序列中,我嘗試了不同的解決方案,離開回調完好。從this answer借用,我用帳戶的訪問,讓我檢查時,被刪除了:

class Account < ActiveRecord::Base 
    before_destroy :disable_user_check_if_admin 
    before_destroy :enable_user_check_if_admin 

    has_many :users, :dependent => :destroy 
    attr_accessor :destroying 

    def disable_user_check_if_admin 
    self.destroying = true 
    end 

    def enable_user_check_if_admin 
    self.destroying = false 
    end 
end 

class User < ActiveRecord::Base 
    before_destroy :check_if_admin 
    has_many :contacts, :dependent => :restrict 

    def check_if_admin 
    return if self.account.destroying 
    false if self.is_admin 
    end 
end 

該做的工作,但它並沒有「聞」的權利被設置和檢查這樣的標誌,所以我回到跳過/設置回調使用:prepend => :true

相關問題