Class level Exception handling

Hi

Could anyone teach me about the following?

  1. in a File.open do … end block, if I call break or return to exit
    the block, will the file be closed?

  2. Is there a way to write a class-level exception handler? See the
    following:

class A
def method 1
begin

rescue
end
end
def method 2
begin

rescue
end
end
end

in the above code, I do a lot of TCP Socket related work in method1
method2 etc. I would like to return false for all these methods if
there’s any error, can I do better than use a begin/rescue/end for every
of them?

Shannon

Hi,

  1. in a File.open do … end block, if I call break or return to exit
    the block, will the file be closed?

Yes.

  1. Is there a way to write a class-level exception handler?

Currently no such way. AspectR may help you. But I have no
confidence.

						matz.
···

In message “class level Exception handling” on 03/03/21, Xiangrong Fang xrfang@hotmail.com writes:

Hi

Could anyone teach me about the following?

  1. in a File.open do … end block, if I call break or return to exit
    the block, will the file be closed?

I guess yes, as it uses rb_ensure.

  1. Is there a way to write a class-level exception handler? See the
    following:

class A
def method 1
begin

rescue
end
end
def method 2
begin

rescue
end
end
end

in the above code, I do a lot of TCP Socket related work in method1
method2 etc. I would like to return false for all these methods if
there’s any error, can I do better than use a begin/rescue/end for every
of them?

batsman@tux-chan:/tmp$ expand -t2 < p.rb

module WrapMethod
def block(meth)
@blocks[meth]
end
def wrap(*args, &block)
@blocks ||= {}
args.each do |meth|
alias_method “#{meth.to_s}”.intern, meth
@blocks[meth] = block
module_eval <<-EOF
def #{meth.to_s}(*args,&b)
begin
return #{meth.to_s}(*args,&b)
rescue Exception
return self.class.block(:#{meth.to_s}).call
end
end
EOF
end
end
end

class A
extend WrapMethod
def foo; raise “BAD THING”; end
def bar; raise “and another!”; end
def baz; “GOOD”; end

wrap :foo, :bar, :baz do
puts “Got #{$!.inspect}”
false
end
end

a = A.new
puts a.foo, a.bar, a.baz
batsman@tux-chan:/tmp$ ruby p.rb
Got #<RuntimeError: BAD THING>
Got #<RuntimeError: and another!>
false
false
GOOD

···

On Fri, Mar 21, 2003 at 01:08:30AM +0900, Xiangrong Fang wrote:


_ _

__ __ | | ___ _ __ ___ __ _ _ __
'_ \ / | __/ __| '_ _ \ / ` | ’ \
) | (| | |
__ \ | | | | | (| | | | |
.__/ _,
|_|/| || ||_,|| |_|
Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com

Let’s call it an accidental feature.
–Larry Wall

I’m not convinced this is a good idea, because by eating the exceptions,
a lot of good error information could be lost. With that in mind, how
about:

class A
def handle_exceptions
begin
yield
return true
rescue
return false
end
end

def method1
  handle_exceptions do
    puts "just testing"
    raise RuntimeError
  end
end

def method2
  handle_exceptions do
    puts "no problem here"
  end
end

end

method1 will return false, because in Ruby, the last value evaluated
in a method gets returned.

Paul

···

On Fri, Mar 21, 2003 at 01:08:30AM +0900, Xiangrong Fang wrote:

in the above code, I do a lot of TCP Socket related work in method1
method2 etc. I would like to return false for all these methods if
there’s any error, can I do better than use a begin/rescue/end for every
of them?

“Mauricio Fernández” batsman.geo@yahoo.com schrieb im Newsbeitrag
news:20030320164056.GA11459@student.ei.uni-stuttgart.de

Hi

Could anyone teach me about the following?

  1. in a File.open do … end block, if I call break or return to exit
    the block, will the file be closed?

I guess yes, as it uses rb_ensure.

Right.

module WrapMethod
def block(meth)
@blocks[meth]
end
def wrap(*args, &block)
@blocks ||= {}
args.each do |meth|
alias_method “#{meth.to_s}”.intern, meth
@blocks[meth] = block
module_eval <<-EOF
def #{meth.to_s}(*args,&b)
begin
return #{meth.to_s}(*args,&b)
rescue Exception
return self.class.block(:#{meth.to_s}).call
end
end
EOF
end
end
end

Did I miss something or do you store the same block in @block for each
method? If so, why? The original poster wanted to have a single error
handler for all methods.

Another suggestion I would make is to change the rescue clause to:

    rescue Exception => e
      return self.class.__block__(:#{meth.to_s}).call(e)
    end

and then

wrap :foo, :bar, :baz do |ex|
puts “Got #{ex.inspect}”
false
end

This is more explicit and provides for easier access to the exception,
because you need not remember that the exception is stored in $!.

Regards

robert
···

On Fri, Mar 21, 2003 at 01:08:30AM +0900, Xiangrong Fang wrote:

Great! This is much simpler than the last approaches. However, I’d make a
small change:

“Paul Brannan” pbrannan@atdesk.com schrieb im Newsbeitrag
news:20030321160054.GV24880@atdesk.com

I’m not convinced this is a good idea, because by eating the exceptions,
a lot of good error information could be lost. With that in mind, how
about:

class A
def handle_exceptions
begin
yield

“return true” removed

  rescue
    return false
  end
end

Regards

robert

Did I miss something or do you store the same block in @block for each
method? If so, why? The original poster wanted to have a single error
handler for all methods.

I thought he could perhaps change his mind :slight_smile:

wrap :some_method do
foo
end

wrap :some_other do
bar
end

My code will work if he wants the same block for all methods, and
it allows further “expansion”.

If there was only one handler per class, the usage of the module could
be simplified to just

class A
extend ClassMethodsWrapper #only needed once in the class hierarchy

wrap do # optional args, see below
# moreover, if properly done, the wrapper can be inherited
# too
end
end

with some magic involving

  • Module#extend_object
  • Module#method_added

I’m not doing that however cause I’m getting a very strong ‘déjà vu’
feeling, after writing KeywordProcessor and NoOverloading :wink:
I mean, I love playing with singleton classes and so, but using the same
tricks again a again spoils the fun.

Another suggestion I would make is to change the rescue clause to:

    rescue Exception => e
      return self.class.__block__(:#{meth.to_s}).call(e)
    end

and then

wrap :foo, :bar, :baz do |ex|
puts “Got #{ex.inspect}”
false
end

This is more explicit and provides for easier access to the exception,
because you need not remember that the exception is stored in $!.

Could be useful; the following too:
rescue Exception
return self.class.block(:#{meth.to_s}).call([:#{meth.to_s}, block] + args)
end

wrap :foo, :bar, :baz do |meth, block, *args|
puts “Got #{$!.inspect} when calling #{meth} with args #{args.inspect}”
# can moreover do something with block
end

···

On Fri, Mar 21, 2003 at 02:58:15AM +0900, Robert Klemme wrote:


_ _

__ __ | | ___ _ __ ___ __ _ _ __
'_ \ / | __/ __| '_ _ \ / ` | ’ \
) | (| | |
__ \ | | | | | (| | | | |
.__/ _,
|_|/| || ||_,|| |_|
Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com

C is quirky, flawed, and an enormous success
– Dennis M. Ritchie

"return true" removed

Great, now try this (with the previous definition of #method2)

   if ! A.new.method2
      puts "failed !"
   end

:slight_smile:

p.s. : gsub(/\breturn\b/, '')

Guy Decoux

No it isn’t :slight_smile:

It cannot get simpler than

extend WrapMethod

And it follows DRY, although at a (admittedly) high cost. The good news
is that the cost is for me when writing WrapMethod, not for the user. :slight_smile:

···

On Sat, Mar 22, 2003 at 01:22:43AM +0900, Robert Klemme wrote:

Great! This is much simpler than the last approaches. However, I’d make a
small change:


_ _

__ __ | | ___ _ __ ___ __ _ _ __
'_ \ / | __/ __| '_ _ \ / ` | ’ \
) | (| | |
__ \ | | | | | (| | | | |
.__/ _,
|_|/| || ||_,|| |_|
Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com

Never trust an operating system you don’t have sources for. :wink:
– Unknown source

“Mauricio Fernández” batsman.geo@yahoo.com schrieb im Newsbeitrag
news:20030320202229.GB15038@student.ei.uni-stuttgart.de

Did I miss something or do you store the same block in @block for each
method? If so, why? The original poster wanted to have a single error
handler for all methods.

I thought he could perhaps change his mind :slight_smile:

:-))

I’m not doing that however cause I’m getting a very strong ‘déjà vu’
feeling, after writing KeywordProcessor and NoOverloading :wink:
I mean, I love playing with singleton classes and so, but using the same
tricks again a again spoils the fun.

I see. The fun thing plays an important role when doing ruby - it’s so much
fun doing things in ruby that are much more difficult in other languages.
:-))

Could be useful; the following too:
rescue Exception
return self.class.block(:#{meth.to_s}).call([:#{meth.to_s}, block] +
args)
end

wrap :foo, :bar, :baz do |meth, block, *args|
puts “Got #{$!.inspect} when calling #{meth} with args
#{args.inspect}”
# can moreover do something with block
end

Si. Although this tends again into the direction of doing method specific
error handling. :slight_smile:

Regards

robert
···

On Fri, Mar 21, 2003 at 02:58:15AM +0900, Robert Klemme wrote:

I think he meant that it is a simpler implementation, not that it is
simpler to use.

This is the same mistake that some people make with templates in C++.
They complain that template meta-programming is too hard, that
frameworks that use template tricks are too complex, or that template
code is just too ugly. But there is an important difference between
a library that is implemented with templates (ugly) and using that
library (not so ugly, usually).

Paul

···

On Sat, Mar 22, 2003 at 02:52:54AM +0900, Mauricio Fernández wrote:

On Sat, Mar 22, 2003 at 01:22:43AM +0900, Robert Klemme wrote:

Great! This is much simpler than the last approaches. However, I’d make a
small change:

No it isn’t :slight_smile:

It cannot get simpler than

extend WrapMethod

“Mauricio Fernández” batsman.geo@yahoo.com schrieb im Newsbeitrag
news:20030321175250.GA31815@student.ei.uni-stuttgart.de

Great! This is much simpler than the last approaches. However, I’d
make a
small change:

No it isn’t :slight_smile:

It cannot get simpler than

extend WrapMethod

Did you suggest this already? Then I’ve overlooked it. Sorry.

And it follows DRY, although at a (admittedly) high cost. The good news
is that the cost is for me when writing WrapMethod, not for the user.
:slight_smile:

Clearly.

robert
···

On Sat, Mar 22, 2003 at 01:22:43AM +0900, Robert Klemme wrote: