【问题标题】:Rescue given anonymous module instead of exception class救援给定匿名模块而不是异常类
【发布时间】:2013-01-25 02:18:51
【问题描述】:

我们可以在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...

【问题讨论】:

  • 专业提示:如果你正确地格式化代码,它会变得更容易阅读和理解。
  • @SergioTulentsev - 是的,你之前也这么跟我说过,我一直牢记在心,就像我对教授所做的那样。在这里,我试图保持不变,但失败了。很抱歉,也请原谅我。 :(
  • 别担心,继续努力:)

标签: ruby exception


【解决方案1】:

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

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

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

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

【讨论】:

  • 作为一个愚蠢的男孩,我想我需要更多的解释.. :(。我只是首先想知道 Ruby 是如何允许通过该方法的,因为它被指示为 ruby​​ -not to pass anything except class or module。请帮助我这里先消化一下。
  • @TheMiddleMan:ruby 中的一切都是一个表达式。计算表达式以产生它们的值。表达式Array 的值本身就是一个Array 类(正如人们所期望的那样)。 errors_with_message 的值是一个动态创建的模块。因此,满足除了类或模块之外不传递任何东西的要求。
  • 天啊!你给了你可能不知道的有价值的陈述,它减少了我接下来的所有困惑。这就是为什么我需要你。请分享您的email ID。 :)
  • 能否请你也打破这个结构 - (class &lt;&lt; m; self; end).instance_eval do define_method(:===) do |e| pattern === e.message end end 我也用这个结构折叠,无法从那里返回。
  • 我不会解释这个具体的结构,而是向你推荐这本书:Metaprogramming Ruby。看完(理解)之后,你就可以自己制作出这样的MP魔法了:)
猜你喜欢
  • 2021-10-24
  • 1970-01-01
  • 1970-01-01
  • 2013-04-18
  • 2012-05-08
  • 1970-01-01
  • 1970-01-01
  • 2012-02-26
  • 1970-01-01
相关资源
最近更新 更多