From: Dave Burt Date: 2006-03-29T14:48:42+09:00 Subject: Re: Can anyone see the obvious msitake I've made? Kev Jackson wrote: > Can anyone see the obvious msitake I've made? It's "msitake" - should be "mistake" ;) No, really... > ... > @@ie.text_field(:id, > @test_data['pg_401']['tel_no_2_fld']).value=@test_data['pg_401']['tel_no_2'] > .. > > It looks like a perfect place to use a macro to write out the call to > ie.text_field at run-time (especially because of the duplicated variables) > > I've written a method_missing method in my base class and tried to > implement something like > @@ie.text_field(:id, > @test_data['pg_401']['tel_no_1_fld']).value=@test_data['pg_401']['tel_no_1'] > => text :id, :pg_401, :tel_no_1 > ... > Now I've changed @@ie to $ie as it makes more sense (watir and I only want > to be driving one ie window at once, so make it a global) This is the obvious solution to me: # call: text "pg_401", "tel_no_1" def text(test_id, field_name) $ie.text_field(:id, $test_data[test_id][field_name + '_fld']).value = $test_data[test_id][field_name] end > in my method_missing definition I have > > when /text/=~m.id2name That will match any method call with "text" in the name. Why do you want that? Just define the method you want ("text"). > #works > $ie.text_field(:id, > eval("$test_data['#{args[1].to_s}']['#{args[2]}_fld']").to_s).set(eval("$test_data['#{args[1].to_s}']['#{args[2]}']")) You should not need eval to do this. Not at all. The above line is the same as: $ie.text_field(:id, ($test_data[args[1].to_s][args[2].to_s + '_fld']).to_s).set( $test_data[args[1].to_s][args[2].to_s]) Which you can simplify to this if you assume args[1] and args[2] are strings: $ie.text_field(:id, $test_data[args[1]][args[2] + '_fld']).set($test_data[args[1]][args[2]]) Summary: less string interpolation, less to_s, and no eval. Keep it simple, just deal with variables. You're just making it needlessly complicated and confusing yourself. > #doesn't work args[0] = id > $ie.text_field("#{args[0].to_sym}", > eval("$test_data['#{args[1].to_s}']['#{args[2]}_fld']")).set(eval("$test_data['#{args[1].to_s}']['#{args[2]}']")) Let's look at this: "#{args[0].to_sym}" args[0] is being cast to Symbol, then back to String because it's being interpolated into one. Hint: "#{x}" is just a strange way of writing x.to_s. If you expect x to be a string, it's the same as just plain old x. "Anything in between quotes" will always give you a string. So, removing the evals and string interpolations, we get: $ie.text_field(args[0].to_sym.to_s, $test_data[args[1].to_s][args[2].to_s + '_fld']).set( $test_data[args[1].to_s][args[2].to_s]) And then we can remove all the to_s: the first one is an error (the obvious mistake you're trying to locate), and the rest are unnecessary if we assume we're being passed a string: $ie.text_field(args[0].to_sym, $test_data[args[1]][args[2] + '_fld']).set( $test_data[args[1]][args[2]]) A little easier on the eyes? > What I want to do is to create a call to $ie.text_field with the correct > params - as you can see if I specify the symbol :id, it works perfectly > (not sure eval is the correct thing to use but it works), however if I try > to get the symbol from the args[] and then to_sym before executing, I > always get > > testScenario(NewApplicationTest): > Watir::Exception::UnknownObjectException: Unable to locate object, using > id and > form:address1 I would expect Watir to be a little more helpful by either accepting the "id" that you're passing, or telling you that it doesn't know how to locate objects using a string rather than the symbol it's expecting. I'll ask Bret about improving this. (As I explained earlier in this message, your "to_sym" was interpolated into a string, so you were sending a string to text_field.) > However I've just tried (as I was typing this email) > $ie.text_field(eval("args[0].to_sym"), > eval("$test_data['#{args[1].to_s}']['#{args[2]}_fld']")).set(eval("$test_data['#{args[1].to_s}']['#{args[2]}']")) > > And it works! :( > > Can anyone explain why #{args[0].to_sym} is not actually evaluating to the > :id symbol, but eval(args[0].to_sym) does? Especially as the error > produced from watir is exactly the same as if I'd have typed: "#{1 + 1}" is the same as (1 + 1).to_s, as I explained earlier. eval("1 + 1") is the same as (1 + 1). Cheers, Dave