0

我有以下方法:

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:在 reduce 中将 next 与累加器参数一起使用。

谷歌搜索该错误导致我到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
4

2 回答 2

2

使用您的示例代码,似乎next(results)确实为我解决了这个问题。我使用了一些抛出 aKeyError而不是NoMethodErroror的测试代码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],而 @Алексей Кузнецов 的示例将nil在每次发生异常时分配给哈希。

于 2016-05-23T13:45:32.803 回答
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
于 2016-05-23T12:28:25.840 回答