【问题标题】:Ruby on Rails: caching data in an objectRuby on Rails:在对象中缓存数据
【发布时间】:2014-11-12 12:14:18
【问题描述】:

我遇到了一个我不知道如何解决的问题。我是 Ruby 和 Rails 的新手,肯定有一种简单的方法可以实现我正在寻找的东西。

这是show 视图的ERB,显示两条相等的线:

<p><%= @user.foo %></p>
<p><%= @user.foo %></p>

想象foo 是一种密集的计算方法,所以我想缓存第一次调用的结果,以便在第二行中使用它,而不必再次调用foo。最简单的选择是定义一个变量并缓存它:

<% foo_cache = @user.foo %>
<p><%= foo_cache %></p>
<p><%= foo_cache %></p>

但我不想弄乱“全局”范围。更好的方法是 foo 本身可以保存第一次调用时返回的值的缓存:

def foo
    return self.cached_foo if self.cached_foo  #WARNING: pseudocode here!
    #Not cached. Do stuff
    ...
    self.cached_foo = computed_value
    computed_value
end

我的问题是,是否可以在不干扰背后模型的情况下动态地将数据附加到对象实例(即不让save 和公司函数处理这些附加数据)。或者也许有另一种更好的方法来实现我正在寻找的东西?

谢谢。

【问题讨论】:

    标签: ruby-on-rails ruby memoization


    【解决方案1】:

    你要找的东西叫做记忆化

    def foo
      @foo ||= calculate_foo
    end
    
    def calculate_foo
       # heavy stuff
    end
    

    感谢conditional assignment (the||=)

    这是一个广泛的话题,所以我会给你一些关于它的链接:

    http://rails-bestpractices.com/posts/59-use-memoization

    http://gavinmiller.io/2013/basics-of-ruby-memoization/

    加上高级记忆,以防您需要做更复杂的事情,例如参数、存储 nil 值

    http://gavinmiller.io/2013/advanced-memoization-in-ruby/

    事实上,Active Support 有 memoizable,但它已被弃用,然后被提取到 gem 中

    如果您想使用它,请查看: https://github.com/matthewrudy/memoist

    【讨论】:

      【解决方案2】:

      这被称为 memoization,它是 ruby​​ 中的一个常见习语。通常是这样表达的:

      def foo
        @cached_foo ||= begin
          # do your heavy stuff here
        end
      end
      

      @cached_foo 不应干扰 ActiveRecord(比如让它尝试将 cached_foo 保存到数据库中)。

      【讨论】:

      • 我知道 ||= 运算符,但我怀疑在根据数据库模型构造的对象中创建实例变量是否合法。我以为它会干扰后面的持久层。所以,如果我没记错的话,持久层会去掉模型中没有的变量。对吗?
      • IIRC,activerecord不使用实例变量来操作(即使对于真实字段)。所以是的,您可以安全地创建实例变量,并且在保存操作期间它们将被忽略。
      【解决方案3】:

      应该这样做。而且不要害怕,实例变量对持久层没有影响。

      def foo
        @foo ||= compute_foo
      end
      
      private
      
      def compute_foo
        # ...
      end
      

      【讨论】:

        猜你喜欢
        • 2018-11-07
        • 1970-01-01
        • 2012-07-18
        • 1970-01-01
        • 2010-09-15
        • 2012-09-24
        • 2011-08-28
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多