【问题标题】:Ruby on Rails decorator for caching a result?用于缓存结果的 Ruby on Rails 装饰器?
【发布时间】:2014-05-05 17:19:00
【问题描述】:

在 Python 中,您可以编写一个装饰器来记忆函数的响应。

Ruby on Rails 有类似的东西吗?我有一个模型的查询方法,我想缓存它。

我知道我可以在方法内部做一些事情,比如:

def foo(param)
  if self.cache[param].nil?
    self.cache[param] = self.get_query_result(param)
  else
    self.cache[param]
  end
end

但是,鉴于我经常这样做,我更喜欢装饰器语法。它更清晰更好的 IMO。

Ruby on Rails 有类似的东西吗?

【问题讨论】:

    标签: ruby-on-rails ruby caching decorator memoization


    【解决方案1】:

    http://martinfowler.com/bliki/TwoHardThings.html:

    计算机科学中只有两个难点:缓存失效和命名。

    -- 菲尔·卡尔顿

    Rails 有很多内置缓存(包括查询缓存)。您可能不需要做任何事情:

    http://guides.rubyonrails.org/caching_with_rails.html

    这是最近一篇关于滚动自己的缓存问题的博文:

    http://cmme.org/tdumitrescu/blog/2014/01/careful-what-you-memoize/

    【讨论】:

      【解决方案2】:

      我通常使用自定义访问器、实例变量和||= 运算符来做到这一点:

      def foo
        @foo ||= something_or_other
      end
      

      something_or_other 可以是同一类上的私有方法,它返回 foo 应该是的对象。

      编辑

      这是一个稍微复杂一点的解决方案,它允许您根据用于调用它们的参数缓存任何方法。

      class MyClass
        attr_reader :cache
        def initialize
          @cache = {}
        end
      
        class << self
          def cacheable(symbol)
            alias_method :"_#{symbol}_uncached", symbol
      
            define_method(symbol) do |*args|
              cache[[symbol, *args]] ||= (send :"_#{symbol}_uncached", *args)
            end
          end
        end
      end
      

      这是如何工作的:

      class MyClass
        def foo(a, b)
          a + b
        end
      
        cacheable :foo
      end
      

      首先,方法是正常定义的。然后调用类方法cacheable,它将原始方法别名为一个新名称,然后在原始名称下重新定义它,仅当它尚未缓存时才执行。它首先使用相同的方法和参数检查缓存中的任何内容,如果存在则返回值,如果不存在则执行原始方法。

      【讨论】:

      • 嗯,我想这不是一个很好的解决你的问题的方法。敬请期待。
      猜你喜欢
      • 1970-01-01
      • 2011-12-13
      • 2012-07-03
      • 1970-01-01
      • 1970-01-01
      • 2012-09-24
      • 1970-01-01
      • 2016-02-24
      • 2020-05-12
      相关资源
      最近更新 更多