views:

86

answers:

2

There seems to be an odd discrepancy between the messages contained in Ruby Exceptions raised directly and raised from within evals. For instance, the following code:

def foo
 raise "Help!"
end

puts "\nRescue foo"
begin
 foo
rescue RuntimeError => e
 puts e.message
end

puts "\nRescue eval 'foo'"
begin
 eval "foo"
rescue RuntimeError => e
 puts e.message
end

Produces the following output:

Rescue foo
Help!

Rescue eval 'foo'
./temp.rb:2:in `foo': Help!

Short of using regexps to sub it out, is there any way I can raise the exception without the context in the second case?

+1  A: 

That is unusual, I've not come across that before. I can't see a way of persuading eval not to add that information, so either you do the regexp munging you mentioned, or you can define your own error type:

class MyError < RuntimeError
  attr_accessor :my_message
  def initialize(m)
    @my_message = m.dup
    super
  end
end

def foo
 raise MyError.new("Help!")
end

puts "\nRescue eval 'foo'"
begin
 eval "foo"
rescue RuntimeError => e
 puts e.my_message
end

With output:

Rescue eval 'foo'
Help!

In anything larger than a simple script, defining your own error types is good practice anyway.

(updated to fix code in line with what Chris said in his answer)

Daniel Lucraft
+2  A: 

Thanks. I was defining my own error anyway, so that's an easy fix.

I've made a slight change, so that the superclass is initialized as well:

class MyException < RuntimeError
  attr_accessor :my_message
  def initialize(m)
    @my_message = String.new(m)
    super
  end
end

(the String.new call seems to be needed to avoid getting the old behaviour again; presumably Exception.new modifies the message in-place.)

Good points all.
Daniel Lucraft