繁体   English   中英

Rails的辅助方法记忆

[英]Rails Memoization of Helper method

我有一个辅助方法,该方法执行昂贵的计算并返回Hash ,并且该Hash在我的整个应用程序生命周期中都是恒定的(这意味着它只能在重新部署后才能更改),并且也不接受任何参数。

为了提高性能,我希望可以“缓存”生成的Hash

不想用Rails缓存对于这一点,因为我想避免额外的行程Memcached和我不想要的反序列串入一个散列的开销。

我的第一个想法是将结果哈希分配给Constant并在其上调用.freeze 但是帮助程序是一个实例方法,常量始终存在于类中,我不得不执行以下超级hacky解决方案:

module FooHelper

def expensive_calculation_method
  resulting_hash
end

EXPENSIVE_CALCULATION_CONSTANT = Class.new.extend(self).expensive_calculation_method.freeze

这是由于helper方法是实例方法,helper是Module(导致伪类扩展,所以我可以调用实例方法),并且我还必须在实例方法之后声明常量AFTER(如果我正确声明的话)在module FooHelper ,我得到了一个undefined method 'expensive_calculation_method'

第二个想法是使用记忆,但是至少对于Rails Controller来说,记忆是在单个请求的生命周期内变量的持久性,因此仅当您在单个请求中多次重复使用变量时才有价值,这不是我的想法。情况,但同时Helpers是模块,而不是要实例化的类,并且到目前为止,我不知道该怎么做。

我将如何缓存该哈希,或以对请求的持久化方式对其进行记忆?

如果要在启动时缓存某些痛苦的操作的结果,请执行以下操作:

module MyExpensiveOperation
  COMPUTED_RESULT = OtherModule.expensive_operation

  def self.cached
    COMPUTED_RESULT
  end
end

只需确保以某种方式加载了该模块,否则该模块将不会启动。 您始终可以在environment.rb或作为config/initializer类型文件强制require该模块。

如果要延迟加载,其基本原理是相同的:

module MyExpensiveOperation
  def self.cached
    return @cached if (defined?(@cached))

    @cached = OtherModule.expensive_operation
  end
end

这将处理由于任何原因返回nilfalse 它将运行一次,并且只能运行一次,除非您有多个线程同时触发它。 如果是这种情况,则可以通过自动锁定来使您的模块并发感知。

根据您的评论,这只会在应用程序启动时发生变化,因此将其放在初始化程序中就可以解决问题。

# config/initializers/expensive_thing.rb
$EXENSIVE_THING_GLOBAL = expensive_calculation

# or
EXPENSIVE_THING_CONSTANT = expensive_calculation

# or

Rails.application.config.expensive_thing = expensive_calcualatioin

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM