我有以下方法:
def fetch_something
@fetch_something ||= array_of_names.inject({}) do |results, name|
begin
results[name] = fetch_value!(name)
rescue NoMethodError, RuntimeError
next
end
results
end
end
达到目的:它为可能引发错误的给定name
获取一个值,在这种情况下,它将忽略name
并尝试下一个。
虽然这很好但我从Rubocop那里得到一个错误:
Lint / NextWithoutAccumulator:使用next和accumulator参数 减少。
谷歌搜索该错误导致我http://www.rubydoc.info/gems/rubocop/0.36.0/RuboCop/Cop/Lint/NextWithoutAccumulator,它说不会省略累加器,这将导致一个方法如下:
def fetch_something
@fetch_something ||= array_of_names.inject({}) do |results, name|
begin
results[name] = fetch_value!(name)
rescue NoMethodError, RuntimeError
next(name)
end
results
end
end
问题是,这种改变打破了其他工作方法。关于如何解决的任何想法?
更新:示范示例:array_of_names = ['name1','name2','name3']
def fetch_value!(name)
# some code that raises an error if the name doesn't correspond to anything
end
fetch_something
# => {'name1' => {key1: 'value1', ...}, 'name3' => {key3: 'value3', ...}}
# 'name2' is missing since it wasn't found durcing the lookup
答案 0 :(得分:2)
使用您的示例代码,似乎next(results)
确实为我解决了问题。我使用了一些抛出KeyError
代替NoMethodError
或RuntimeError
的测试代码,但这个想法仍然相同:
@array_of_names = ['name1','name2','name3']
def fetch_value!(name)
{'name1' => 'n1', 'name3' => 'n3'}.fetch(name)
end
def fetch_something
@fetch_something ||= @array_of_names.inject({}) do |results, name|
begin
results[name] = fetch_value!(name)
rescue NoMethodError, RuntimeError, KeyError
next(results)
end
results
end
end
p fetch_something
此代码输出:
{"name1"=>"n1", "name3"=>"n3"}
此外,我同意@АлексейКузнецовeach_with_object
可能是你的块代码改变你正在尝试构建的数据结构的方式。所以fetch_something
的首选实现可能更像是这样:
def fetch_something
@fetch_something ||= @array_of_names.each_with_object({}) do |name, results|
begin
results[name] = fetch_value!(name)
rescue NoMethodError, RuntimeError, KeyError
# error handling
end
end
end
请注意,在我的示例中,begin
/ end
块外分配给results[name]
,而@АлексейКузнецо的示例将分配{{每次发生异常时都会发生哈希值。
答案 1 :(得分:0)
只需使用each_with_object
def fetch_something
@fetch_something ||= array_of_names.each_with_object({}) do |name, results|
results[name] ||= begin
fetch_value!(name)
rescue NoMethodError, RuntimeError
end
end
end