Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to rescue an eval in Ruby?

I'm trying to figure out how to rescue syntax errors that come up when eval()ing code in Ruby 1.8.6.

I would expect the following Ruby code:

#!/usr/bin/ruby  good_str = "(1+1)" bad_str = "(1+1"    # syntax error: missing closing paren  begin     puts eval(good_str)     puts eval(bad_str) rescue => exc     puts "RESCUED!" end 

to produce the following result when run:

2 RESCUED! 

Instead, what I get is:

2 eval_rescue.rb:8: (eval):1: compile error (SyntaxError) (eval):1: syntax error, unexpected $end, expecting ')' 

It appears that the SyntaxError raised by the eval method is being rescued somewhere within the eval, without giving me a chance to handle it myself.

Anybody have any idea how to get the behavior I want (i.e., for my 'rescue' clause to catch the error from the 'eval')?

like image 807
Brent Chapman Avatar asked Feb 12 '09 19:02

Brent Chapman


People also ask

How does eval work in Ruby?

Ruby's eval takes in a string as the argument, which means that it is possible for one to accept user input or read code off of a file and get it evaluated from within your program - essentially re-programming the way your program behaves.

What is rescue keyword in Ruby?

In Ruby, we use the rescue keyword for that. When rescuing an exception in Ruby, you can specify a specific error class that should be rescued from. begin raise 'This exception will be rescued!' rescue StandardError => e puts "Rescued: #{e.inspect}" end.


2 Answers

Brent already got an answer that works, but I recommend rescuing from the smallest set of exceptions you can get away with. This makes sure you're not accidentally gobbling up something you don't mean to be.

Thus,

begin   puts eval(good_str)   puts eval(bad_str) rescue SyntaxError => se   puts 'RESCUED!' end 
like image 58
James A. Rosen Avatar answered Sep 30 '22 21:09

James A. Rosen


Well, that was easy...

It turns out that, by default, the "rescue" statement does not catch all exceptions, but only those that are subclasses of StandardError. SyntaxError is a sibling/cousin of StandardError, not a subclass of it, so the rescue statement doesn't capture it unless explicitly told to.

To have the rescue block capture all exceptions, you need to change the code to the following:

#!/usr/bin/ruby  good_str = "(1+1)" bad_str = "(1+1"    # syntax error: missing closing paren  begin     puts eval(good_str)     puts eval(bad_str) rescue Exception => exc     puts "RESCUED!" end 

Note the change in the "rescue" line, from "rescue => exc" to "rescue Exception => exc".

Now, when you run the code, you get the desired results:

2 RESCUED! 
like image 40
Brent Chapman Avatar answered Sep 30 '22 23:09

Brent Chapman