Memoize 多行方法 - Rails
Memoize multi-line method - Rails
我在使用 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
显然,这行不通,但我现在有点卡住了。
如果您想为同一功能记忆单独的 input/output 对,记忆会稍微复杂一些。由于您在此处没有输入,并且每次都期望或允许输出相同,因此记忆非常简单。像这样:
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
,在这种情况下。
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
变量名称从 @manager
命名为 @managers
因为它包含一个数据列表。
我经常分开这样的方法:
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
通常,这也使它们更容易测试。
您可以使用 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
我在使用 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
显然,这行不通,但我现在有点卡住了。
如果您想为同一功能记忆单独的 input/output 对,记忆会稍微复杂一些。由于您在此处没有输入,并且每次都期望或允许输出相同,因此记忆非常简单。像这样:
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
,在这种情况下。
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
变量名称从 @manager
命名为 @managers
因为它包含一个数据列表。
我经常分开这样的方法:
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
通常,这也使它们更容易测试。
您可以使用 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