救援给定匿名模块而不是异常类

时间:2013-02-09 11:06:07

标签: ruby exception

我们可以在rescue语句之后放置一个类或模块,但是在下面的代码中,我看到rescue之后的方法,它不适合这种模式。它是如何工作的以及如何产生它设计用于显示的输出?

def errors_with_message(pattern)
  # Generate an anonymous "matcher module" with a custom threequals
  m = Module.new
  (class << m; self; end).instance_eval do
    define_method(:===) do |e|
      pattern === e.message
    end
  end
  m
end
puts "About to raise"
begin
  raise "Timeout while reading from socket"
rescue errors_with_message(/socket/)
  puts "Ignoring socket error"
end
puts "Continuing..."

输出

About to raise
Ignoring socket error
Continuing...

1 个答案:

答案 0 :(得分:4)

Rescue需要一个类或一个模块,为true。因此,该方法创建具有特殊行为的匿名模块。您会看到,当rescue搜索处理程序时,它会将===运算符应用于您提供的异常类/模块,并将实际异常作为参数传递。

begin
  # do something
rescue MyCustomError
  # process your error
rescue StandardError
  # process standard error
end

因此,如果引发StandardError(或其后代之一),将跳过第一个处理程序并匹配第二个处理程序。

现在,来自errors_with_message的模块很特别。它重新定义了三元运算符以匹配异常消息。因此,如果引发错误并且其消息包含单词“socket”,则此处理程序将匹配。很酷的伎俩,嗯?