如何捕获类中的所有错误?

时间:2014-09-12 14:08:42

标签: ruby

这是我正在尝试做的事情:

class Foo
  def foo
    raise "lol noob"
  end

  # ... many other methods here ...

rescue StandardError => e
  puts "error caught: #{e}"
end


Foo.new.foo
RuntimeError: lol noob
from (pry):45:in `foo'

如您所见,这不起作用。

我想避免的是将rescue块放入每个方法中,因为它们很多。可能吗?如果没有,最佳做法是什么?

3 个答案:

答案 0 :(得分:2)

为一个班级设一个共同的救援区是没有意义的,每个方法都做不同的事情吗?你会如何以同样的方式处理各种错误?错误处理与方法的“主要”部分一样,也是逻辑的一部分。

这里没有灵丹妙药,你可以在需要的地方进行救援,并在需要时做所需的事情。

如果您想了解一些常见的最佳做法,可能会感兴趣Exceptional Ruby本书。

答案 1 :(得分:2)

TL; DR

在Ruby中,你通常需要使用rescue而不是接收器来包装调用者

说明

您可能会发现这种行为令人惊讶,因为您并未将类视为可执行代码。类定义中的rescue子句将捕获在解释类时引发的异常。请考虑以下示例:

class Foo
  raise 'bar'
rescue
  'Rescued!'
end
#=> "Rescued!"

这里,rescue子句有效,因为在类代码执行时会引发异常。但是,一些Foo #bar方法通常不会被这个子句拯救(除非被定义),因为Foo不再是调用者,而是接收者。

类的救援子句将捕获在定义类本身时引发的异常。但是,要在运行时在方法中进行救援,您需要在调用者(在本例中为#bar方法)内进行救援,如下所示:

class Foo
  def bar
    raise 'method exception'
  rescue
    'Rescued method exception.'
  end
end

Foo.new.bar
#=> "Rescued method exception."

答案 2 :(得分:1)

如果你完全确定你需要做的唯一错误处理就是注销错误,你可以通过定义一个包含块的帮助器方法并执行错误处理来抽象出一些重复的错误记录。那里。

例如,

class Foo
  def foo
    handle_exception do
      raise "lol noob"
    end
  end

  def bar
    handle_exception do
      raise "rofl"
    end
  end

  def handle_exception
    yield
  rescue => e
    puts "error caught: #{e}"
  end
end

Foo.new.foo # error caught: lol noob
Foo.new.bar # error caught: rofl

这样做的好处是,在您决定想要一些替代行为(即添加回溯)之后,您只需要触摸一行代码:

def handle_exception
  yield
rescue => e
  puts "error caught: #{e}\n#{e.backtrace.join("\n")}"
end