一種選擇是臨時覆蓋負責更新緩存計數的方法,以防銷燬。 例如,如果你有以下兩種模式
class Category < ActiveRecord::Base
has_many :products
end
class Product < ActiveRecord::Base
belongs_to :category, counter_cache: true
end
現在,你可以嘗試找到負責更新緩存的方法有以下
2.1.5 :038 > Product.new.methods.map(&:to_s).grep(/counter_cache/)
指望這表明所有這些都是counter_cache相關產品的實例方法與結果如下
=> ["belongs_to_counter_cache_before_destroy_for_category", "belongs_to_counter_cache_after_create_for_category", "belongs_to_counter_cache_after_update_for_category"]
從方法的名稱就說明
"belongs_to_counter_cache_after_create_for_category"
可能在銷燬後負責計數器緩存更新。 所以我決定暫時覆蓋此方法以一個假的方法,它不會做任何事情(跳過櫃檯緩存更新)
Product.class_eval do
def fake_belongs_to_counter_cache_before_destroy_for_category; end
alias_method :real_belongs_to_counter_cache_before_destroy_for_category, :belongs_to_counter_cache_before_destroy_for_category
alias_method :belongs_to_counter_cache_before_destroy_for_category, :fake_belongs_to_counter_cache_before_destroy_for_category
end
現在,如果你將摧毀任何產品的對象,也不會更新分類計數緩存表。 但是,在運行代碼來銷燬特定對象之後,恢復實際方法非常重要。要恢復到實際的類方法,你可以做以下
Product.class_eval do
alias_method :belongs_to_counter_cache_before_destroy_for_category, :real_belongs_to_counter_cache_before_destroy_for_category
remove_method :real_belongs_to_counter_cache_before_destroy_for_category
remove_method :fake_belongs_to_counter_cache_before_destroy_for_category
end
爲了確保方法定義總是恢復後您的具體銷燬任務,你可以寫一個類的方法,這將確保同時運行倍率和恢復代碼
class Product < ActiveRecord::Base
belongs_to :category, counter_cache: true
def self.without_counter_cache_update_on_destroy(&block)
self.class_eval do
def fake_belongs_to_counter_cache_before_destroy_for_category; end
alias_method :real_belongs_to_counter_cache_before_destroy_for_category, :belongs_to_counter_cache_before_destroy_for_category
alias_method :belongs_to_counter_cache_before_destroy_for_category, :fake_belongs_to_counter_cache_before_destroy_for_category
end
yield
self.class_eval do
alias_method :belongs_to_counter_cache_before_destroy_for_category, :real_belongs_to_counter_cache_before_destroy_for_category
remove_method :real_belongs_to_counter_cache_before_destroy_for_category
remove_method :fake_belongs_to_counter_cache_before_destroy_for_category
end
end
end
現在,如果你摧毀任何產品對象給出以下
Product.without_counter_cache_update_on_destroy { Product.last.destroy }
它不會更新類別表計數器緩存。
參考文獻:
加載ActiveModel禁用回調https://jeffkreeftmeijer.com/2010/disabling-activemodel-callbacks/ 臨時覆蓋方法:https://gist.github.com/aeden/1069124
如果你確定以跳過所有回調,您可以用'Model.first。刪除' –
是的我知道方法來跳過回調,但我有一個特殊的需要,只禁用計數器回調。現在,我使用'destroy_all',然後重置計數器(這看起來很浪費)。 –