如何在Rails中记忆类方法?

时间:2013-04-21 14:57:31

标签: ruby-on-rails ruby-on-rails-3

我有一个带有类方法的模型,计算量很大,每次请求都会多次调用。

理想情况下,我想在单个请求的持续时间内缓存结果。

在这种情况下,最佳做法是什么?

示例:

class MyClass < ActiveRecord::Base
  def self.heavy_method; ... ; end
end

然后在帮手

def helper
  MyClass.heavy_method
end

此助手在许多视图中使用

2 个答案:

答案 0 :(得分:15)

这是一个非常通用的解决方案,可能适合您。

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

请注意,在类变量中存储内容可能会导致线程安全问题,因为缓存的结果将在线程之间共享。

如果这可能是您的应用程序的问题,您可能希望将数据存储在线程中而不是使用类变量。

答案 1 :(得分:3)

感谢@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而不是将值保留在内存中可能是更好的解决方案。