views:

614

answers:

2

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">}>
]
+2  A: 

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!

btelles
@btelles: works! so what's difference between your code and http://mechanize.rubyforge.org/mechanize/WWW/Mechanize/Form/Field.html public method class new for field?
Radek
I thought that `login_form['field_name']='value'` doesn't work because I was trying to add the field and not to modify. Maybe somebody can elaborate on that if one have more knowledge about that.
Radek
If you click the "show source" for the []= method, you'll see that the implementation creates a field if one doesn't already exist by running the "add_field!" method. It says "does a field already exist by that name?" if not, then "add_field!(field_name, value)"...
btelles
+3  A: 

another way how to add new field is to so at the time of posting the form

page = agent.post( url, {'auth_username'=>'myusername',   #existing field
                         'auth_password'=>'mypassword',   #existing field
                         'auth_login'=>'Login'})   #new field
Radek