我有一个带有类方法的模型,该方法计算量很大,每个请求我都会调用很多次。
理想情况下,我想在单个请求期间缓存结果。
在这种情况下,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
请注意,将内容存储在类变量中可能会导致线程安全问题,因为缓存的结果将在线程之间共享。
如果这可能是您的应用程序的问题,您可能希望将数据存储在线程中,而不是使用类变量。
感谢@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
而不是将值保存在内存中。