how to add new field to mechanize form (ruby/mechanize)

mechanize, ruby, webforms

Solution

I think what you're looking for is

login_form.add_field!(field_name, value = nil)

Here are the docs:

http://rdoc.info/projects/tenderlove/mechanize

The difference between this and the method WWW::Mechanize::Form::Field.new is not much, aside from the fact that there aren't many ways to add fields to a form. Here's how the add_field! method is implemented....you can see that it's exactly what you'd expect. It instantiates a Field object, then adds it to the form's 'fields' array. You wouldn't be able to do this in your code because the method "fields<<" is a private method inside "Form."

# File lib/www/mechanize/form.rb, line 65
  def add_field!(field_name, value = nil)
    fields << Field.new(field_name, value)
  end

On a side note, according to the docs you should be able to do the first variation you proposed:

login_form['field_name']='value'

Hope this helps!

Problem

there is a public class method to add field to mechanize form I tried .. ``` #login_form.field.new('auth_login','Login') #login_form.field.new('auth_login','Login') ``` and both gives me an error `undefined method "new" for #<WWW::Mechanize::Form::Field:0x3683cbc> (NoMethodError)` I tried `login_form.field.new('auth_login','Login')` which gives me an error ``` mechanize-0.9.3/lib/www/mechanize/page.rb:13 n `meta': undefined method `search' for nil:NilClass (NoMethodError) ``` but at the time I submit the form. The field does not exist in html source. I want to add it so POST query sent by my script will contain `auth_username=myusername&auth_password=mypassword&auth_login=Login` So far it sends only `auth_username=radek&auth_password=mypassword` which might be why I cannot get logged in. Just my thought. The script looks like ``` require 'rubygems' require 'mechanize' require 'logger' agent = WWW::Mechanize.new {|a| a.log = Logger.new("loginYOTA.log") } agent.follow_meta_refresh = true #Mechanize does not follow meta refreshes by default, we need to set that option. page = agent.get("http://www.somedomain.com/login?auth_successurl=http://www.somedomain.com/forum/yota?baz_r=1") login_form = page.form_with(:method => 'POST') puts login_form.buttons.inspect puts page.forms.inspect #STDIN.gets login_form.fields.each { |f| puts "#{f.name} : #{f.value}" } login_form['auth_username'] = 'radeks' login_form['auth_password'] = 'TestPass01' #login_form['auth_login'] = 'Login' #login_form.field.new('auth_login','Login') #login_form.field.new('auth_login','Login') #login_form.fields.each { |f| puts "#{f.name} : #{f.value}" } #STDIN.gets page = agent.submit login_form #Display welcome message if logged in puts page.parser.xpath("/html/body/div/div/div/table/tr/td[2]/div/strong").xpath('text()').to_s.strip puts puts page.parser.xpath("/html/body/div/div/div/table/tr/td[2]/div").xpath('text()').to_s.strip output = File.open("login.html", "w") {|f| f.write(page.parser.to_html) } ``` The .inspect of the form looks like ``` [#<WWW::Mechanize::Form {name nil} {method "POST"} {action "http://www.somedomain.com/login?auth_successurl=http://www.somedomain.com/forum/yota?baz_r=1"} {fields #<WWW::Mechanize::Form::Field:0x36946c0 @name="auth_username", @value=""> #<WWW::Mechanize::Form::Field:0x369451c @name="auth_password", @value="">} {radiobuttons} {checkboxes} {file_uploads} {buttons #<WWW::Mechanize::Form::Button:0x36943b4 @name="auth_login", @value="Login">}> ] ```

Original source