![]() |
Dynamic method execution problem
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 |
Re: Dynamic method execution problem
On 9/9/05, joe.yakich@gmail.com <joe.yakich@gmail.com> wrote:
<snip definition of methods array> > # 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 |
Re: Dynamic method execution problem
Jacob,
Wow, that's much cleaner and clearer. It even works, too. :-) Thank you! Joe |
Re: Dynamic method execution problem
> [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/ |
| All times are GMT. The time now is 10:02 AM. |
Powered by vBulletin®. Copyright ©2000 - 2013, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.