exceptions and eval'ing a string

C

Chris Hall

Here's my situation


I have a setup such as:

----task.rb----
class Task
def initialize(name, &action)
@name = name
@action = action
end

def run
@action.call(self)
end
end

----task_runner.rb----
require 'task'

t = Task.new('task_1') { |t| puts t.name }
t.run # => thing


what i am now trying to do is put the Task creation code inside a file
and eval that as a string

----thing.task----
Task.new('task_1') P |t| puts t.name }


----task_runner.rb----
require 'task'
def load_task
@t = eval('thing.task')
end

@t = nil
load_task
@t.run

and this works...however, the difference is that if an exception is
thrown as part of the Task's action (when it is run) eval craps out with
an exception like

(eval):15

and it brings down the entire script, which is a bad thing because i'm
running each task in a thread. this doesn't happen obviously when i'm
not eval'ing.

can someone explain to me what is going on? I'm thinking it's a
scoping/context thing, but i'm not really sure.

Chris
 
C

Chris Hall

sorry, there's a typo in the example, that eval line should read

@t = eval(IO.read("test.task"))

rather than

@t = eval("test.task")

problem still stands.
 
J

Jano Svitok

Here's my situation
and this works...however, the difference is that if an exception is
thrown as part of the Task's action (when it is run) eval craps out with
an exception like

(eval):15

and it brings down the entire script, which is a bad thing because i'm
running each task in a thread. this doesn't happen obviously when i'm
not eval'ing.

You can handle those exceptions by adding 'rescue' clause to your run method.
i.e.
def run
begin
@action.call...
rescue Exception => ex
# do whatever you want with ex
end
end

You have to
Note: in this case the begin and end may be omitted:

def run
@action.call...
rescue Exception => ex
# do whatever you want with ex
end

To catch syntax errors, you have to add begin/rescue/end around the
eval command.

Have a look at ruby exception hierarchy in zenspider's Ruby QuickRef,
and carefully consider what do you want to catch and what not (to
allow ctrl-break to function etc.)

Finally, you can control exception propagation using Thread.abort_on_exception.

HTH,

Jano
 
R

Robert Klemme

Here's my situation


I have a setup such as:

----task.rb----
class Task
def initialize(name, &action)
@name = name
@action = action
end

def run
@action.call(self)
end
end

----task_runner.rb----
require 'task'

t = Task.new('task_1') { |t| puts t.name }
t.run # => thing


what i am now trying to do is put the Task creation code inside a file
and eval that as a string

----thing.task----
Task.new('task_1') P |t| puts t.name }
^
I'd say you get a syntax error here.
----task_runner.rb----
require 'task'
def load_task
@t = eval('thing.task')
end

@t = nil
load_task
@t.run

and this works...however, the difference is that if an exception is
thrown as part of the Task's action (when it is run) eval craps out with
an exception like

(eval):15

That statement seems illogical, because eval is only used for loading
the task but you claim that eval throws during execution of the task.
What am I missing here?
and it brings down the entire script, which is a bad thing because i'm
running each task in a thread. this doesn't happen obviously when i'm
not eval'ing.

can someone explain to me what is going on? I'm thinking it's a
scoping/context thing, but i'm not really sure.

Personally I dislike the way you use instance variables here. Why don't
you just let load_task return the new Task and assign the result to a
local variable?

Kind regards

robert
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,236
Members
46,825
Latest member
VernonQuy6

Latest Threads

Top