3

I try to access a form using mechanize (Ruby). On my form I have a gorup of Radiobuttons. So I want to check one of them.

I wrote:

target_form = (page/:form).find{ |elem| elem['id'] == 'formid'}
target_form.radiobutton_with(:name => "radiobuttonname")[2].check

In this line I want to check the radiobutton with the value of 2. But in this line, I get an error:

: undefined method `radiobutton_with' for #<Nokogiri::XML::Element:0x9b86ea> (NoMethodError)
Phrogz
  • 296,393
  • 112
  • 651
  • 745
Newbie
  • 1,644
  • 5
  • 29
  • 40
  • 1
    According to the docs, your form should be of `Mechanize::Form` class, not `Nokogiri::XML::Element`. How did you get `target_form`? – Mladen Jablanović Mar 18 '10 at 11:06
  • target_form: target_form = (page/:form).find { |elem| elem['id'] == 'formid'} – Newbie Mar 18 '10 at 11:20
  • You should use `Mechanize::Page#form_with` method to get the form. BTW, I am not sure that your page is `Mechanize::Page` at all. – Mladen Jablanović Mar 18 '10 at 11:51
  • page = agent.get('http://www.mypage.xy') thats how i define page – Newbie Mar 18 '10 at 11:58
  • puts page.class will return WWW::Mechanize::Page Now I tried catching my form tag with xpath, cause there is no other way i know to get an element by id: target_form = page.search '//*[@id="myformid"]' puts target_form.class will return Nokogiri::XML::NodeSet – Newbie Mar 18 '10 at 12:09
  • The easiest way I was able to find a Mechanize form by id is `page.forms.find{|f| f.form_node['id'] == 'myformid'}` – Mladen Jablanović Mar 18 '10 at 13:25
  • Well, using your way, catching the form, i get another error: : undefined method `[]' for # (NoMethodError) at line: target_form.radiobutton_with(:name => "radiobuttonname")[2].check Don't know why, but my form is still a WWW::Mechanize::Page Object as before, but now it seems to go on a little more. – Newbie Mar 18 '10 at 15:37
  • 2
    I presume you have multiple radiobuttons with the same name, and you need the third. In that case, just call `radiobuttons_with` instead of `radiobutton_with` method (note the plural). – Mladen Jablanović Mar 18 '10 at 15:54

1 Answers1

6

The problem occured because using a Mechanize page as a Nokogiri document (by calling the / method, or search, or xpath, etc.) returns Nokogiri elements, not Mechanize elements with their special methods.

As noted in the comments, you can be sure to get a Mechanize::Form by using the form_with method to find your form instead.

Sometimes, however, you can find the element you want with Nokogiri but not with Mechanize. For example, consider a page with a <select> element that is not inside a <form>. Since there is no form, you can't use the Mechanize field_with method to find the select and get a Mechanize::Form::SelectList instance.

If you have a Nokogiri element and you want the Mechanize equivalent, you can create it by passing the Nokogiri element to the constructor. For example:

sel = Mechanize::Form::SelectList.new( page.at_xpath('//select[@name="city"]') )

In your case where you had a Nokogiri::XML::Element and wanted a Mechanize::Form:

# Find the xml element
target_form = (page/:form).find{ |elem| elem['id'] == 'formid'}
target_form = Mechanize::Form.new( target_form )

P.S. The first line above is more simply achieved by target_form = page.at_css('#formid').

Phrogz
  • 296,393
  • 112
  • 651
  • 745
  • To actually be able to submit the form you would have to change your last line to `target_form = Mechanize::Form.new(target_form, mech_object, page)` – raphinesse Feb 05 '12 at 13:52
  • @raphinesse Oh? I'll take your word for it. What is the `mech_object` object? – Phrogz Feb 05 '12 at 14:18
  • Your 'agent', the `Mechanize` object. See [Mechanize::Form#new docs](http://mechanize.rubyforge.org/Mechanize/Form.html#method-c-new) for more details. If you take a look at [Mechanize::Form#submit's source](http://mechanize.rubyforge.org/Mechanize/Form.html#method-i-submit) you'll notice that it tries to call `@mech.submit` which will fail when no `mech` argument was provided. The same is true for the `page` argument I guess. – raphinesse Feb 05 '12 at 14:35
  • One last thing: In the most recent version of Mechanize there seems to be no `Mechanize::Page#at_css`. `Mechanize::Page#at` works fine however... – raphinesse Feb 05 '12 at 14:40