Ruby:如果引发异常,则跳过循环元素

时间:2016-05-23 10:53:29

标签: ruby-on-rails ruby loops ruby-on-rails-4 rubocop

我有以下方法:

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

2 个答案:

答案 0 :(得分:2)

使用您的示例代码,似乎next(results)确实为我解决了问题。我使用了一些抛出KeyError代替NoMethodErrorRuntimeError的测试代码,但这个想法仍然相同:

@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