Dynamic method execution problem

J

joe.yakich

All,

I have been trying to figure out a way to execute a series of methods,
only 1 of which is expected to actually run without exception, in a
particular order. I haven't figured out how to use send or Method#call,
so I was messing with eval, but not with much success (I have problems
with argument passing, calling the right method, and so on.)

I have been trying this, but it doesn't quite work. (As background
information, I'm using the Watir test library, and I want to interact
with a web page that may have 1 of 4 different elements, each of which
I have methods to access and use.)

# Each item in this array is a different method name (I changed the
names to
# "methodn" from more useful names for the purposes of this question)
methods = [
"method1",
"method2",
"method3",
"method4"
]

# The ie variable here refers to a Watir::IE object
begin
my_method = methods.shift
puts "Trying #{my_method}"
eval "#{my_method}(ie)"
end

rescue UnknownObjectException
if methods.length > 0
retry
else
raise
end

Any suggestions? I'm new to Ruby, so perhaps there's a totally
different approach that is the standard way to address this. (I was
trying stuff inspired from PickAxe 2nd Ed, pg.112 and pg.407-409).

Thanks in advance!

Joe
 
J

Jacob Fugal

On 9/9/05 said:
# The ie variable here refers to a Watir::IE object
begin
my_method =3D methods.shift
puts "Trying #{my_method}"
eval "#{my_method}(ie)"
end
=20
rescue UnknownObjectException
if methods.length > 0
retry
else
raise
end

First, a fix... you don't want the end to the begin block until after
the rescue, example:

begin
# do risky operation
rescue
# recover from failure
end

Then, translating to use send instead of eval:

begin
my_method =3D methods.shift
puts "Trying #{my_method}"
send(my_method.to_sym, ie)
rescue UnknownObjectException
retry unless methods.empty?
raise
end

(I also changed the content of the rescue clause to something that
flows a bit nicer for me, but this is just a style issue. What you had
works fine)

The send method sends the method identified by the first argument to
the receiver (here the implicit self) with the remainder of the
arguments.

Myself, rather than using retry, I'd do something like this:

methods =3D [ :method1, :method2, ... ]

methods.find do |method|
puts "Trying #{method}"
begin
send( method, ie )
method
rescue
end
end or raise "No applicable method found"

This makes the nature of looping through the methods more explicit,
rather than relying on a combination of .shift, .empty? and retry.

Jacob Fugal
 
J

joe.yakich

Jacob,

Wow, that's much cleaner and clearer. It even works, too. :)

Thank you!

Joe
 
B

Brian Schröder

[snip]=20
begin
my_method =3D methods.shift
puts "Trying #{my_method}"
send(my_method.to_sym, ie)
rescue UnknownObjectException
retry unless methods.empty?
raise
end

You don't need to convert my_method to a symbol explicitly. Just pass
it on, and send will handle it on its own. That way you don't take on
responsibility for argument checking of send and if somehow send is
changed to take something that can not be represented as a symbol -
and your code gets feeded with it - the code will continue to work.
The send example may be silly because it's unlikely to change, but I
think it is a general guideline not to assume too much about the
called methods but let the called methods figure it out for
themeselves. Also I don't think this is opposed to "fail early" but
that would be open to some discussion by people more intelligent than
me.

best regards,

Brian
[snip]
=20
Jacob Fugal
=20
=20


--=20
http://ruby.brian-schroeder.de/

Stringed instrument chords: http://chordlist.brian-schroeder.de/
 

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

Similar Threads


Members online

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,906
Latest member
SkinfixSkintag

Latest Threads

Top