我有一個類方法的模型,它在計算中很沉重,我每次請求調用很多次。如何在Rails中記憶一個類方法?
理想情況下,我想緩存一個請求的持續時間的結果。
在這種情況下,最佳實踐是什麼?
例子:
class MyClass < ActiveRecord::Base
def self.heavy_method; ... ; end
end
然後在助手
def helper
MyClass.heavy_method
end
該輔助許多意見
我有一個類方法的模型,它在計算中很沉重,我每次請求調用很多次。如何在Rails中記憶一個類方法?
理想情況下,我想緩存一個請求的持續時間的結果。
在這種情況下,最佳實踐是什麼?
例子:
class MyClass < ActiveRecord::Base
def self.heavy_method; ... ; end
end
然後在助手
def helper
MyClass.heavy_method
end
該輔助許多意見
這是一個非常通用的解決方案,可能適合你。
class Klass
def self.memoized_expensive_method
@memoized_expensive_method_result ||= expensive_method
end
def self.expensive_method
# ...
end
end
然後,如果您想確保您的代碼在每次請求時都被重新執行,您可以在控制器中使用過濾器。
class Klass
def self.reset_expensive_method_cache!
@memoized_expensive_method_result = nil
end
end
class ApplicationController
before_filter :reset_klass_expensive_method_cache
def reset_klass_expensive_method_cache
Klass.reset_expensive_method_cache!
end
end
注意,在類變量存儲的東西可能會導致線程安全問題,因爲高速緩存的結果將在線程之間共享。
如果這可能是您的應用程序的問題,您可能需要將數據存儲在線程中而不是使用類變量。
很好的回答。不過,更簡單的重置會解決所有類實例變量。 'self.instance_variables.each {| v | instance_variable_set(v,nil)}' – steel 2016-04-06 21:07:21
值得注意的是,您可能會使用帶有多個線程的Web服務器。同時在不同線程上的兩個請求將競爭和爭奪緩存。使用此解決方案緩存每個請求是不可取的。 [RequestStore](https://github.com/steveklabnik/request_store)gem是線程安全的 – JustinBull 2017-08-22 16:00:38
使用你能不能只拘泥於結果的變量?對於通用緩存,memcache將是適當的。
爲了獲得更好,更完整的答案,請提供有關您問題的更多詳細信息。
感謝@unixcharles,這裏是我最終做
class SomeClass
@lock = Mutex.new
after_save :clear_cached_calculation
class << self
def some_calculation
@lock.synchronize do
@calc ||= heavy_operation
end
end
def clear_calculation
@lock.synchronize do
@calc = nil
end
end
end
private
def clear_cached_caculation
SomeClass.clear_calculation
end
end
編輯:
這可能是一個更好的解決方案使用Rails.cache.fetch
,而不是保持值在內存中。
什麼類的類?換句話說,它住在哪裏?它是一種類方法(與實例相反)是否合理?它是怎麼叫的;它跨多個對象嗎? – 2013-04-21 14:59:21