views:

114

answers:

2

I'm using mechanize and have a problem on one form... the form has two select boxes with the same name.

How can I select the second one?

ie. NumNights second occurrence.

i found in the docs something like this:

form.set_fields( :foo => ['bar', 1] )

but this didn't work:

form.field_with(:name => [ 'NumNights', 2 ]).options[no_days.to_i-1].select
+2  A: 

Get a reference to a form, and iterate over the members. Something like this :

my_fields = form.fields.select {|f| f.name == "whatever"}
my_fields[1].whatever = "value"

After you're done filling in the forms, submit it. I haven't ran this code, but I think it should work.

Geo
that works beautifully, thanks!
holden
you're welcome!
Geo
A: 

Geo has a decent solution, but there's a few missed opportunities there.

If you're only finding one element, it's probably more efficient to use Enumerable#find instead of Enumerable#select and then Array#first on top of that. Alternatively, you can simply do the reassignment during the select.

If you look at the suggested approach there's a chance you'll trigger an exception if a field with that name is not found:

# Original approach
my_fields = form.fields.select {|f| f.name == "whatever"}
# Chance of exception here, calling nil#whatever=
my_fields[1].whatever = "value"

I'd advocate using Enumerable#select and simply doing the work inside the loop, much safer that way:

my_fields = form.fields.select do |f|
  if (f.name == "whatever")
    # Will only ever trigger if an element is found,
    # also works if more than one field has same name.
    f.whatever = 'value'
  end
end

The other approach is to use Enumerable#find which returns at most one element:

# Finds only a single element
whatever_field = form.fields.find { |f| f.name == "whatever" }
whatever_field and whatever_field.whatever = 'value'

Of course you can always pepper your code with exception catches, but that seems counter-productive.

tadman