Parent

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]

(Not documented)

action[RW]

(Not documented)

name[RW]

(Not documented)

fields[R]

(Not documented)

buttons[R]

(Not documented)

file_uploads[R]

(Not documented)

radiobuttons[R]

(Not documented)

checkboxes[R]

(Not documented)

enctype[RW]

(Not documented)

form_node[R]

(Not documented)

page[R]

(Not documented)

Public Class Methods

new(node, mech=nil, page=nil) click to toggle source

(Not documented)

# File lib/mechanize/form.rb, line 35
    def initialize(node, mech=nil, page=nil)
      @enctype = node['enctype'] || 'application/x-www-form-urlencoded'
      @form_node        = node
      @action           = Util.html_unescape(node['action'])
      @method           = (node['method'] || 'GET').upcase
      @name             = node['name']
      @clicked_buttons  = []
      @page             = page
      @mech             = mech

      parse
    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
    def [](field_name)
      f = field(field_name)
      f && f.value
    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
    def []=(field_name, value)
      f = field(field_name)
      if f.nil?
        add_field!(field_name, value)
      else
        f.value = value
      end
    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
    def add_button_to_query(button)
      @clicked_buttons << button
    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
    def add_field!(field_name, value = nil)
      fields << Field.new({'name' => field_name}, value)
    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
    def build_query(buttons = [])
      query = []

      (fields + checkboxes).sort.each do |f|
        case f
        when Form::CheckBox
          if f.checked
            qval = proc_query(f)
            query.push(*qval)
          end
        when Form::Field
          qval = proc_query(f)
          query.push(*qval)
        end
      end

      radio_groups = {}
      radiobuttons.each do |f|
        fname = from_native_charset(f.name)
        radio_groups[fname] ||= []
        radio_groups[fname] << f
      end

      # take one radio button from each group
      radio_groups.each_value do |g|
        checked = g.select {|f| f.checked}

        if checked.size == 1
          f = checked.first
          qval = proc_query(f)
          query.push(*qval)
        elsif checked.size > 1
          raise "multiple radiobuttons are checked in the same group!"
        end
      end

      @clicked_buttons.each { |b|
        qval = proc_query(b)
        query.push(*qval)
      }
      query
    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
    
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
    
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
    
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
    
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
    def click_button(button = buttons.first)
      submit(button)
    end
delete_field!(field_name) click to toggle source

Removes all fields with name field_name.

# File lib/mechanize/form.rb, line 237
    def delete_field!(field_name)
      @fields.delete_if{ |f| f.name == field_name}
    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
    
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
    
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
    
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
    
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
    def has_field?(field_name)
      ! fields.find { |f| f.name.eql? field_name }.nil?
    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

(Not documented)

# File lib/mechanize/form.rb, line 55
    def has_value?(value)
      ! fields.find { |f| f.value.eql? value }.nil?
    end
hidden_field?(field_name) click to toggle source

(Not documented)

# File lib/mechanize/form.rb, line 72
    def hidden_field?(field_name)   !!  hiddens.find{|f| f.name == field_name}; end
hiddens() click to toggle source

(Not documented)

# File lib/mechanize/form.rb, line 66
    def hiddens  ; @hiddens   ||=  fields.select { |f| f.class == Hidden   }; end
keys() click to toggle source

(Not documented)

# File lib/mechanize/form.rb, line 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
    def method_missing(id,*args)
      method = id.to_s.gsub(/=$/, '')
      if field(method)
        return field(method).value if args.empty?
        return field(method).value = args[0]
      end
      super
    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
    
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
    
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
    def request_data
      query_params = build_query()
      case @enctype.downcase
      when /^multipart\/form-data/
        boundary = rand_string(20)
        @enctype = "multipart/form-data; boundary=#{boundary}"
        params = []
        query_params.each { |k,v| params << param_to_multipart(k, v) unless k.nil? }
        @file_uploads.each { |f| params << file_to_multipart(f) }
        params.collect { |p| "--#{boundary}\r\n#{p}" }.join('') +
          "--#{boundary}--\r\n"
      else
        Mechanize::Util.build_query_string(query_params)
      end
    end
reset_button?(button_name) click to toggle source

(Not documented)

# File lib/mechanize/form.rb, line 70
    def reset_button?(button_name)  !!   resets.find{|f| f.name == button_name}; end
resets() click to toggle source

(Not documented)

# File lib/mechanize/form.rb, line 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
    def set_fields(fields = {})
      fields.each do |k,v|
        case v
        when Hash
          v.each do |index, value|
            self.fields_with(:name => k.to_s).[](index).value = value
          end
        else
          value = nil
          index = 0
          [v].flatten.each do |val|
            index = val.to_i unless value.nil?
            value = val if value.nil?
          end
          self.fields_with(:name => k.to_s).[](index).value = value
        end
      end
    end
submit(button=nil, headers = {}) click to toggle source

Submit this form with the button passed in

# File lib/mechanize/form.rb, line 140
    def submit button=nil, headers = {}
      @mech.submit(self, button, headers)
    end
submit_button?(button_name) click to toggle source

(Not documented)

# File lib/mechanize/form.rb, line 69
    def submit_button?(button_name) !!  submits.find{|f| f.name == button_name}; end
submits() click to toggle source

(Not documented)

# File lib/mechanize/form.rb, line 63
    def submits  ; @submits   ||= buttons.select { |f| f.class == Submit   }; end
text_field?(field_name) click to toggle source

(Not documented)

# File lib/mechanize/form.rb, line 71
    def text_field?(field_name)     !!    texts.find{|f| f.name == field_name}; end
textarea_field?(field_name) click to toggle source

(Not documented)

# File lib/mechanize/form.rb, line 73
    def textarea_field?(field_name) !!textareas.find{|f| f.name == field_name}; end
textareas() click to toggle source

(Not documented)

# File lib/mechanize/form.rb, line 67
    def textareas; @textareas ||=  fields.select { |f| f.class == Textarea }; end
texts() click to toggle source

(Not documented)

# File lib/mechanize/form.rb, line 65
    def texts    ; @texts     ||=  fields.select { |f| f.class == Text     }; end
values() click to toggle source

(Not documented)

# File lib/mechanize/form.rb, line 61
    def values; fields.map { |f| f.value }; end

Private Instance Methods

file_to_multipart(file) click to toggle source

(Not documented)

# File lib/mechanize/form.rb, line 429
    def file_to_multipart(file)
      file_name = file.file_name ? ::File.basename(file.file_name) : ''
      body =  "Content-Disposition: form-data; name=\"" +
        "#{mime_value_quote(file.name)}\"; " +
        "filename=\"#{mime_value_quote(file_name)}\"\r\n" +
        "Content-Transfer-Encoding: binary\r\n"

      if file.file_data.nil? and ! file.file_name.nil?
        file.file_data = ::File.open(file.file_name, "rb") { |f| f.read }
        file.mime_type = WEBrick::HTTPUtils.mime_type(file.file_name,
                                                      WEBrick::HTTPUtils::DefaultMimeTypes)
      end

      if file.mime_type != nil
        body << "Content-Type: #{file.mime_type}\r\n"
      end

      body <<
        if file.file_data.respond_to? :read
          "\r\n#{file.file_data.read}\r\n"
        else
          "\r\n#{file.file_data}\r\n"
        end

      body
    end
from_native_charset(str) click to toggle source

(Not documented)

# File lib/mechanize/form.rb, line 160
    def from_native_charset str
      Util.from_native_charset(str,page && page.encoding)
    end
mime_value_quote(str) click to toggle source

(Not documented)

# File lib/mechanize/form.rb, line 419
    def mime_value_quote(str)
      str.gsub(/(["\r\\])/){|s| '\\' + s}
    end
param_to_multipart(name, value) click to toggle source

(Not documented)

# File lib/mechanize/form.rb, line 423
    def param_to_multipart(name, value)
      return "Content-Disposition: form-data; name=\"" +
        "#{mime_value_quote(name)}\"\r\n" +
        "\r\n#{value}\r\n"
    end
parse() click to toggle source

(Not documented)

# File lib/mechanize/form.rb, line 349
    def parse
      @fields       = []
      @buttons      = []
      @file_uploads = []
      @radiobuttons = []
      @checkboxes   = []

      # Find all input tags
      form_node.search('input').each do |node|
        type = (node['type'] || 'text').downcase
        name = node['name']
        next if name.nil? && !(type == 'submit' || type =='button')
        case type
        when 'radio'
          @radiobuttons << RadioButton.new(node, self)
        when 'checkbox'
          @checkboxes << CheckBox.new(node, self)
        when 'file'
          @file_uploads << FileUpload.new(node, nil)
        when 'submit'
          @buttons << Submit.new(node)
        when 'button'
          @buttons << Button.new(node)
        when 'reset'
          @buttons << Reset.new(node)
        when 'image'
          @buttons << ImageButton.new(node)
        when 'hidden'
          @fields << Hidden.new(node, node['value'] || '')
        when 'text'
          @fields << Text.new(node, node['value'] || '')
        when 'textarea'
          @fields << Textarea.new(node, node['value'] || '')
        else
          @fields << Field.new(node, node['value'] || '')
        end
      end

      # Find all textarea tags
      form_node.search('textarea').each do |node|
        next if node['name'].nil?
        @fields << Field.new(node, node.inner_text)
      end

      # Find all select tags
      form_node.search('select').each do |node|
        next if node['name'].nil?
        if node.has_attribute? 'multiple'
          @fields << MultiSelectList.new(node)
        else
          @fields << SelectList.new(node)
        end
      end

      # Find all submit button tags
      # FIXME: what can I do with the reset buttons?
      form_node.search('button').each do |node|
        type = (node['type'] || 'submit').downcase
        next if type == 'reset'
        @buttons << Button.new(node)
      end
    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
    def proc_query(field)
      return unless field.query_value
      field.query_value.map{|(name, val)|
        [from_native_charset(name), from_native_charset(val.to_s)]
      }
    end
rand_string(len = 10) click to toggle source

(Not documented)

# File lib/mechanize/form.rb, line 412
    def rand_string(len = 10)
      chars = ("a".."z").to_a + ("A".."Z").to_a
      string = ""
      1.upto(len) { |i| string << chars[rand(chars.size-1)] }
      string
    end

Disabled; run with --debug to generate this.

[Validate]

Generated with the Darkfish Rdoc Generator 1.1.6.