Confusion with "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…”

This is mainly used for “===” overloading when rescue would perform
matching .

That is far thing for me. can anyone help me to understand what the “def
… end” part is doing?

I am totally uncomfortable with the syntax. So break it and help me to
understand what is doing.

On Sat, Feb 9, 2013 at 1:07 PM, Love U Ruby [email protected]
wrote:

matching .
That approach does not work:

irb(main):014:0> module M
irb(main):015:1> def ===(e) /test/ === e.message end
irb(main):016:1> end
=> nil
irb(main):017:0> begin; raise “test”; rescue M => e; p “caught”;
rescue Exception => e; p “uncaught”; else p “nothing” end
“uncaught”
=> “uncaught”

That is far thing for me. can anyone help me to understand what the “def
… end” part is doing?

It defines a new anonymous module which delegates its instance method
=== to instance pattern. It uses a closure which references pattern.

I am totally uncomfortable with the syntax. So break it and help me to
understand what is doing.

class << m; self; end yields the singleton class of m - today we can
simply use m.singleton_class instead.

Then #instance_eval is used to be able to invoke the private method
#define_method. An alternative way would be

m.singleton_class.send(:define_method, :===) { pattern === e.message }

The idea seems to be that rescue works the same as case, i.e. by using
=== of the instances passed to do matching. But it doesn’t (see
above, where I manually recreated that situation). Instead rescue
checks whether the class named is a superclass of the exception
caught. You cannot even use Class#> for that:

irb(main):040:0> o = Object.new
=> #Object:0x802be35c
irb(main):041:0> class <<o; include Comparable; end
=> #<Class:#Object:0x802be35c>
irb(main):042:0> def o.<=>(e) /test/ =~ e.message ? 1 : -1 end
=> nil
irb(main):043:0> begin; raise “test”; rescue o => e; p e; rescue => e;
p “fail” end
“fail”
=> “fail”

A more successful approach is this

begin
rescue => e
case e.message
when /socket/
puts “socket error”
when /file/
puts “file error”
else
puts “no idea: #{e.message}”
end
end

Kind regards

robert