Parent

Class Index [+]

Quicksearch

Mechanize::Form

Synopsis

This class encapsulates a form parsed out of an HTML page. Each type of input fields available in a form can be accessed through this object. See GlobalForm for more methods.

Example

Find a form and print out its fields

 form = page.forms.first # => Mechanize::Form
 form.fields.each { |f| puts f.name }

Set the input field ‘name’ to “Aaron“

 form['name'] = 'Aaron'
 puts form['name']

Attributes

method[RW]
action[RW]
name[RW]
fields[R]
buttons[R]
file_uploads[R]
radiobuttons[R]
checkboxes[R]
enctype[RW]
form_node[R]
page[R]

Public Class Methods

new(node, mech=nil, page=nil) click to toggle source
    # File lib/mechanize/form.rb, line 35
35:     def initialize(node, mech=nil, page=nil)
36:       @enctype = node['enctype'] || 'application/x-www-form-urlencoded'
37:       @form_node        = node
38:       @action           = Util.html_unescape(node['action'])
39:       @method           = (node['method'] || 'GET').upcase
40:       @name             = node['name']
41:       @clicked_buttons  = []
42:       @page             = page
43:       @mech             = mech
44: 
45:       parse
46:     end

Public Instance Methods

[](field_name) click to toggle source

Fetch the value of the first input field with the name passed in

Example

Fetch the value set in the input field ‘name’

 puts form['name']
     # File lib/mechanize/form.rb, line 111
111:     def [](field_name)
112:       f = field(field_name)
113:       f && f.value
114:     end
[]=(field_name, value) click to toggle source

Set the value of the first input field with the name passed in

Example

Set the value in the input field ‘name’ to “Aaron“

 form['name'] = 'Aaron'
     # File lib/mechanize/form.rb, line 120
120:     def []=(field_name, value)
121:       f = field(field_name)
122:       if f.nil?
123:         add_field!(field_name, value)
124:       else
125:         f.value = value
126:       end
127:     end
add_button_to_query(button) click to toggle source

This method adds a button to the query. If the form needs to be submitted with multiple buttons, pass each button to this method.

     # File lib/mechanize/form.rb, line 213
213:     def add_button_to_query(button)
214:       @clicked_buttons << button
215:     end
add_field!(field_name, value = nil) click to toggle source

Add a field with field_name and value

    # File lib/mechanize/form.rb, line 76
76:     def add_field!(field_name, value = nil)
77:       fields << Field.new({'name' => field_name}, value)
78:     end
build_query(buttons = []) click to toggle source

This method builds an array of arrays that represent the query parameters to be used with this form. The return value can then be used to create a query string for this form.

     # File lib/mechanize/form.rb, line 168
168:     def build_query(buttons = [])
169:       query = []
170: 
171:       (fields + checkboxes).sort.each do |f|
172:         case f
173:         when Form::CheckBox
174:           if f.checked
175:             qval = proc_query(f)
176:             query.push(*qval)
177:           end
178:         when Form::Field
179:           qval = proc_query(f)
180:           query.push(*qval)
181:         end
182:       end
183: 
184:       radio_groups = {}
185:       radiobuttons.each do |f|
186:         fname = from_native_charset(f.name)
187:         radio_groups[fname] ||= []
188:         radio_groups[fname] << f
189:       end
190: 
191:       # take one radio button from each group
192:       radio_groups.each_value do |g|
193:         checked = g.select {|f| f.checked}
194: 
195:         if checked.size == 1
196:           f = checked.first
197:           qval = proc_query(f)
198:           query.push(*qval)
199:         elsif checked.size > 1
200:           raise "multiple radiobuttons are checked in the same group!"
201:         end
202:       end
203: 
204:       @clicked_buttons.each { |b|
205:         qval = proc_query(b)
206:         query.push(*qval)
207:       }
208:       query
209:     end
button_with(criteria) click to toggle source

Find one button that matches criteria Example:

  form.button_with(:value => /submit/).value = 'hello'
     # File lib/mechanize/form.rb, line 264
264:     
buttons_with(criteria) click to toggle source

Find all buttons that match criteria Example:

  form.buttons_with(:value => /submit/).each do |button|
    button.value = 'hello!'
  end
     # File lib/mechanize/form.rb, line 273
273:     
checkbox_with(criteria) click to toggle source

Find one checkbox that matches criteria Example:

  form.checkbox_with(:name => /woo/).check
     # File lib/mechanize/form.rb, line 312
312:     
checkboxes_with(criteria) click to toggle source

Find all checkboxes that match criteria Example:

  form.checkboxes_with(:name => /woo/).each do |field|
    field.check
  end
     # File lib/mechanize/form.rb, line 321
321:     
click_button(button = buttons.first) click to toggle source

Submit form using button. Defaults to the first button.

     # File lib/mechanize/form.rb, line 146
146:     def click_button(button = buttons.first)
147:       submit(button)
148:     end
delete_field!(field_name) click to toggle source

Removes all fields with name field_name.

     # File lib/mechanize/form.rb, line 237
237:     def delete_field!(field_name)
238:       @fields.delete_if{ |f| f.name == field_name}
239:     end
field_with(criteria) click to toggle source

Find one field that matches criteria Example:

  form.field_with(:value => /foo/).value = 'hello'
     # File lib/mechanize/form.rb, line 248
248:     
fields_with(criteria) click to toggle source

Find all fields that match criteria Example:

  form.fields_with(:value => /foo/).each do |field|
    field.value = 'hello!'
  end
     # File lib/mechanize/form.rb, line 257
257:     
file_upload_with(criteria) click to toggle source

Find one file upload field that matches criteria Example:

  form.file_upload_with(:file_name => /picture/).value = 'foo'
     # File lib/mechanize/form.rb, line 280
280:     
file_uploads_with(criteria) click to toggle source

Find all file upload fields that match criteria Example:

  form.file_uploads_with(:file_name => /picutre/).each do |field|
    field.value = 'foo!'
  end
     # File lib/mechanize/form.rb, line 289
289:     
has_field?(field_name) click to toggle source

Returns whether or not the form contains a field with field_name

    # File lib/mechanize/form.rb, line 49
49:     def has_field?(field_name)
50:       ! fields.find { |f| f.name.eql? field_name }.nil?
51:     end
Also aliased as: has_key?
has_key?(field_name) click to toggle source
Alias for: has_field?
has_value?(value) click to toggle source
    # File lib/mechanize/form.rb, line 55
55:     def has_value?(value)
56:       ! fields.find { |f| f.value.eql? value }.nil?
57:     end
hidden_field?(field_name) click to toggle source
    # File lib/mechanize/form.rb, line 72
72:     def hidden_field?(field_name)   !!  hiddens.find{|f| f.name == field_name}; end
hiddens() click to toggle source
    # File lib/mechanize/form.rb, line 66
66:     def hiddens  ; @hiddens   ||=  fields.select { |f| f.class == Hidden   }; end
keys() click to toggle source
    # File lib/mechanize/form.rb, line 59
59:     def keys; fields.map { |f| f.name }; end
method_missing(id,*args) click to toggle source

Treat form fields like accessors.

     # File lib/mechanize/form.rb, line 130
130:     def method_missing(id,*args)
131:       method = id.to_s.gsub(/=$/, '')
132:       if field(method)
133:         return field(method).value if args.empty?
134:         return field(method).value = args[0]
135:       end
136:       super
137:     end
radiobutton_with(criteria) click to toggle source

Find one radio button that matches criteria Example:

  form.radiobutton_with(:name => /woo/).check
     # File lib/mechanize/form.rb, line 296
296:     
radiobuttons_with(criteria) click to toggle source

Find all radio buttons that match criteria Example:

  form.radiobuttons_with(:name => /woo/).each do |field|
    field.check
  end
     # File lib/mechanize/form.rb, line 305
305:     
request_data() click to toggle source

This method calculates the request data to be sent back to the server for this form, depending on if this is a regular post, get, or a multi-part post,

     # File lib/mechanize/form.rb, line 220
220:     def request_data
221:       query_params = build_query()
222:       case @enctype.downcase
223:       when /^multipart\/form-data/
224:         boundary = rand_string(20)
225:         @enctype = "multipart/form-data; boundary=#{boundary}"
226:         params = []
227:         query_params.each { |k,v| params << param_to_multipart(k, v) unless k.nil? }
228:         @file_uploads.each { |f| params << file_to_multipart(f) }
229:         params.collect { |p| "--#{boundary}\r\n#{p}" }.join('') +
230:           "--#{boundary}--\r\n"
231:       else
232:         Mechanize::Util.build_query_string(query_params)
233:       end
234:     end
reset_button?(button_name) click to toggle source
    # File lib/mechanize/form.rb, line 70
70:     def reset_button?(button_name)  !!   resets.find{|f| f.name == button_name}; end
resets() click to toggle source
    # File lib/mechanize/form.rb, line 64
64:     def resets   ; @resets    ||= buttons.select { |f| f.class == Reset    }; end
set_fields(fields = {}) click to toggle source

This method sets multiple fields on the form. It takes a list of field name, value pairs. If there is more than one field found with the same name, this method will set the first one found. If you want to set the value of a duplicate field, use a value which is a Hash with the key as the index in to the form. The index is zero based. For example, to set the second field named ‘foo’, you could do the following:

 form.set_fields( :foo => { 1 => 'bar' } )
     # File lib/mechanize/form.rb, line 88
 88:     def set_fields(fields = {})
 89:       fields.each do |k,v|
 90:         case v
 91:         when Hash
 92:           v.each do |index, value|
 93:             self.fields_with(:name => k.to_s).[](index).value = value
 94:           end
 95:         else
 96:           value = nil
 97:           index = 0
 98:           [v].flatten.each do |val|
 99:             index = val.to_i unless value.nil?
100:             value = val if value.nil?
101:           end
102:           self.fields_with(:name => k.to_s).[](index).value = value
103:         end
104:       end
105:     end
submit(button=nil, headers = {}) click to toggle source

Submit this form with the button passed in

     # File lib/mechanize/form.rb, line 140
140:     def submit button=nil, headers = {}
141:       @mech.submit(self, button, headers)
142:     end
submit_button?(button_name) click to toggle source
    # File lib/mechanize/form.rb, line 69
69:     def submit_button?(button_name) !!  submits.find{|f| f.name == button_name}; end
submits() click to toggle source
    # File lib/mechanize/form.rb, line 63
63:     def submits  ; @submits   ||= buttons.select { |f| f.class == Submit   }; end
text_field?(field_name) click to toggle source
    # File lib/mechanize/form.rb, line 71
71:     def text_field?(field_name)     !!    texts.find{|f| f.name == field_name}; end
textarea_field?(field_name) click to toggle source
    # File lib/mechanize/form.rb, line 73
73:     def textarea_field?(field_name) !!textareas.find{|f| f.name == field_name}; end
textareas() click to toggle source
    # File lib/mechanize/form.rb, line 67
67:     def textareas; @textareas ||=  fields.select { |f| f.class == Textarea }; end
texts() click to toggle source
    # File lib/mechanize/form.rb, line 65
65:     def texts    ; @texts     ||=  fields.select { |f| f.class == Text     }; end
values() click to toggle source
    # File lib/mechanize/form.rb, line 61
61:     def values; fields.map { |f| f.value }; end

Private Instance Methods

file_to_multipart(file) click to toggle source
     # File lib/mechanize/form.rb, line 428
428:     def file_to_multipart(file)
429:       file_name = file.file_name ? ::File.basename(file.file_name) : ''
430:       body =  "Content-Disposition: form-data; name=\"" +
431:         "#{mime_value_quote(file.name)}\"; " +
432:         "filename=\"#{mime_value_quote(file_name)}\"\r\n" +
433:         "Content-Transfer-Encoding: binary\r\n"
434: 
435:       if file.file_data.nil? and ! file.file_name.nil?
436:         file.file_data = ::File.open(file.file_name, "rb") { |f| f.read }
437:         file.mime_type = WEBrick::HTTPUtils.mime_type(file.file_name,
438:                                                       WEBrick::HTTPUtils::DefaultMimeTypes)
439:       end
440: 
441:       if file.mime_type != nil
442:         body << "Content-Type: #{file.mime_type}\r\n"
443:       end
444: 
445:       body <<
446:         if file.file_data.respond_to? :read
447:           "\r\n#{file.file_data.read}\r\n"
448:         else
449:           "\r\n#{file.file_data}\r\n"
450:         end
451: 
452:       body
453:     end
from_native_charset(str) click to toggle source
     # File lib/mechanize/form.rb, line 160
160:     def from_native_charset str
161:       Util.from_native_charset(str,page && page.encoding)
162:     end
mime_value_quote(str) click to toggle source
     # File lib/mechanize/form.rb, line 418
418:     def mime_value_quote(str)
419:       str.gsub(/(["\r\\])/){|s| '\' + s}
420:     end
param_to_multipart(name, value) click to toggle source
     # File lib/mechanize/form.rb, line 422
422:     def param_to_multipart(name, value)
423:       return "Content-Disposition: form-data; name=\"" +
424:         "#{mime_value_quote(name)}\"\r\n" +
425:         "\r\n#{value}\r\n"
426:     end
parse() click to toggle source
     # File lib/mechanize/form.rb, line 348
348:     def parse
349:       @fields       = []
350:       @buttons      = []
351:       @file_uploads = []
352:       @radiobuttons = []
353:       @checkboxes   = []
354: 
355:       # Find all input tags
356:       form_node.search('input').each do |node|
357:         type = (node['type'] || 'text').downcase
358:         name = node['name']
359:         next if name.nil? && !(type == 'submit' || type =='button')
360:         case type
361:         when 'radio'
362:           @radiobuttons << RadioButton.new(node, self)
363:         when 'checkbox'
364:           @checkboxes << CheckBox.new(node, self)
365:         when 'file'
366:           @file_uploads << FileUpload.new(node, nil)
367:         when 'submit'
368:           @buttons << Submit.new(node)
369:         when 'button'
370:           @buttons << Button.new(node)
371:         when 'reset'
372:           @buttons << Reset.new(node)
373:         when 'image'
374:           @buttons << ImageButton.new(node)
375:         when 'hidden'
376:           @fields << Hidden.new(node, node['value'] || '')
377:         when 'text'
378:           @fields << Text.new(node, node['value'] || '')
379:         when 'textarea'
380:           @fields << Textarea.new(node, node['value'] || '')
381:         else
382:           @fields << Field.new(node, node['value'] || '')
383:         end
384:       end
385: 
386:       # Find all textarea tags
387:       form_node.search('textarea').each do |node|
388:         next if node['name'].nil?
389:         @fields << Field.new(node, node.inner_text)
390:       end
391: 
392:       # Find all select tags
393:       form_node.search('select').each do |node|
394:         next if node['name'].nil?
395:         if node.has_attribute? 'multiple'
396:           @fields << MultiSelectList.new(node)
397:         else
398:           @fields << SelectList.new(node)
399:         end
400:       end
401: 
402:       # Find all submit button tags
403:       # FIXME: what can I do with the reset buttons?
404:       form_node.search('button').each do |node|
405:         type = (node['type'] || 'submit').downcase
406:         next if type == 'reset'
407:         @buttons << Button.new(node)
408:       end
409:     end
proc_query(field) click to toggle source

This method is sub-method of build_query. It converts charset of query value of fields into expected one.

     # File lib/mechanize/form.rb, line 152
152:     def proc_query(field)
153:       return unless field.query_value
154:       field.query_value.map{|(name, val)|
155:         [from_native_charset(name), from_native_charset(val.to_s)]
156:       }
157:     end
rand_string(len = 10) click to toggle source
     # File lib/mechanize/form.rb, line 411
411:     def rand_string(len = 10)
412:       chars = ("a".."z").to_a + ("A".."Z").to_a
413:       string = ""
414:       1.upto(len) { |i| string << chars[rand(chars.size-1)] }
415:       string
416:     end

Disabled; run with --debug to generate this.

[Validate]

Generated with the Darkfish Rdoc Generator 1.1.6.