On Sat, Feb 9, 2013 at 1:07 PM, Love U Ruby <[email protected]> wrote:
> 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 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
--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/
--
[email protected] |
https://groups.google.com/d/forum/ruby-talk-google?hl=en
---
You received this message because you are subscribed to the Google Groups
"ruby-talk-google" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.