Memoize 多行方法 - Rails

问题描述 投票:0回答:5

我在使用 Rails 之前从未实现过记忆,我认为我遇到了一个很好的用例,但我不确定如何去做。这是我正在使用的:

方法:

 def manager_rep_code_and_name
    manager = []

    rep_code_list.each do |rep_code|
      context = Finfolio::GetManagerByRepCode.call(rep_code: rep_code)

      manager.push({name: context.manager.response.first["Name"], rep_code: rep_code})
    end

    manager
  end

此方法进行网络调用,可能需要一段时间才能弄清楚这一切。有没有什么办法可以

memoize
这种方法,所以如果它已经存在,我就不必出去再次提出这个请求。

像这样的东西:

def manager_rep_code_and_name
   @managers ||= manager = []

   rep_code_list.each do |rep_code|
     context = Finfolio::GetManagerByRepCode.call(rep_code: rep_code)

     manager.push({name: context.manager.response.first["Name"], rep_code: rep_code})
   end

  manager
end

显然,这行不通,但我现在有点卡住了。

ruby-on-rails ruby memoization
5个回答
7
投票

我经常分开这样的方法:

def fetch_manager_rep_code_and_name
  rep_code_list.map do |rep_code|
    context = Finfolio::GetManagerByRepCode.call(rep_code: rep_code)
    { name: context.manager.response.first['Name'], rep_code: rep_code }
  end
end

def manager_rep_code_and_name
  @manager_rep_code_and_name ||= fetch_manager_rep_code_and_name
end

通常,这也使它们更容易测试。


5
投票

您可以使用

begin
end
块来记忆多行代码的结果:

def manager_rep_code_and_name
   @manager_rep_code_and_name ||= begin
     manager = []

     rep_code_list.each do |rep_code|
       context = Finfolio::GetManagerByRepCode.call(rep_code: rep_code)

       manager.push({name: context.manager.response.first["Name"], rep_code: rep_code})
     end

    manager
  end
end

1
投票

如果你想为同一个函数记忆不同的输入/输出对,记忆会稍微复杂一些。由于您在此处没有输入,并且每次都期望或允许输出相同,因此记忆非常简单。像这样的东西:

  def manager_rep_code_and_name
    return @manager if @manager
    @manager = []
    rep_code_list.each do |rep_code|
      context = Finfolio::GetManagerByRepCode.call(rep_code: rep_code)
      @manager.push({name: context.manager.response.first["Name"], rep_code: rep_code})
    end
    @manager
  end

将记忆实例 var 命名为方法名称的下划线版本是一种常见的约定 -

@_manager_rep_code_and_name
,在这种情况下。


1
投票
 def manager_rep_code_and_name
    @managers ||= []
    if @managers.blank?
      @managers = rep_code_list.map do |rep_code|
        context = Finfolio::GetManagerByRepCode.call(rep_code: rep_code)
        {name: context.manager.response.first["Name"], rep_code: rep_code}
      end
    end
    @managers
  end

变量名从

@managers
命名为
@manager
,因为它包含一个数据列表。


0
投票

您可以使用

then
它将返回给定块的值。

def manager_rep_code_and_name
   @manager_rep_code_and_name ||= [].then do |managers|
     rep_code_list.each do |rep_code|
       context = Finfolio::GetManagerByRepCode.call(rep_code: rep_code)

       managers.push({name: context.manager.response.first["Name"], rep_code: rep_code})
    end
  end
end
© www.soinside.com 2019 - 2024. All rights reserved.