Class WWW::Mechanize::Form
In: lib/www/mechanize/form/field.rb
lib/www/mechanize/form/select_list.rb
lib/www/mechanize/form/option.rb
lib/www/mechanize/form/button.rb
lib/www/mechanize/form/image_button.rb
lib/www/mechanize/form/file_upload.rb
lib/www/mechanize/form/check_box.rb
lib/www/mechanize/form/radio_button.rb
lib/www/mechanize/form/multi_select_list.rb
lib/www/mechanize/form.rb
Parent: Object
Mechanize\n[lib/www/mechanize.rb\nlib/www/mechanize/content_type_error.rb\nlib/www/mechanize/cookie.rb\nlib/www/mechanize/cookie_jar.rb\nlib/www/mechanize/file.rb\nlib/www/mechanize/file_saver.rb\nlib/www/mechanize/form.rb\nlib/www/mechanize/form/button.rb\nlib/www/mechanize/form/check_box.rb\nlib/www/mechanize/form/field.rb\nlib/www/mechanize/form/file_upload.rb\nlib/www/mechanize/form/image_button.rb\nlib/www/mechanize/form/multi_select_list.rb\nlib/www/mechanize/form/option.rb\nlib/www/mechanize/form/radio_button.rb\nlib/www/mechanize/form/select_list.rb\nlib/www/mechanize/headers.rb\nlib/www/mechanize/history.rb\nlib/www/mechanize/list.rb\nlib/www/mechanize/monkey_patch.rb\nlib/www/mechanize/page.rb\nlib/www/mechanize/page/base.rb\nlib/www/mechanize/page/frame.rb\nlib/www/mechanize/page/link.rb\nlib/www/mechanize/page/meta.rb\nlib/www/mechanize/pluggable_parsers.rb\nlib/www/mechanize/response_code_error.rb\nlib/www/mechanize/unsupported_scheme_error.rb] lib/www/mechanize/headers.rb WWW dot/m_32_0.png

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 # => WWW::Mechanize::Form
 form.fields.each { |f| puts f.name }

Set the input field ‘name’ to "Aaron"

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

Methods

Classes and Modules

Class WWW::Mechanize::Form::Button
Class WWW::Mechanize::Form::CheckBox
Class WWW::Mechanize::Form::Field
Class WWW::Mechanize::Form::FileUpload
Class WWW::Mechanize::Form::ImageButton
Class WWW::Mechanize::Form::MultiSelectList
Class WWW::Mechanize::Form::Option
Class WWW::Mechanize::Form::RadioButton
Class WWW::Mechanize::Form::SelectList

External Aliases

fields -> elements

Attributes

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

Public Class methods

[Source]

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

Public Instance methods

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']

[Source]

     # File lib/www/mechanize/form.rb, line 98
 98:       def [](field_name)
 99:         f = field(field_name)
100:         f && f.value
101:       end

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'

[Source]

     # File lib/www/mechanize/form.rb, line 107
107:       def []=(field_name, value)
108:         f = field(field_name)
109:         if f.nil?
110:           add_field!(field_name, value)
111:         else
112:           f.value = value
113:         end
114:       end

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

[Source]

     # File lib/www/mechanize/form.rb, line 172
172:       def add_button_to_query(button)
173:         @clicked_buttons << button
174:       end

Add a field with field_name and value

[Source]

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

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.

[Source]

     # File lib/www/mechanize/form.rb, line 134
134:       def build_query(buttons = [])
135:         query = []
136:     
137:         fields().each do |f|
138:           query.push(*f.query_value)
139:         end
140:     
141:         checkboxes().each do |f|
142:           query.push(*f.query_value) if f.checked
143:         end
144:     
145:         radio_groups = {}
146:         radiobuttons().each do |f|
147:           radio_groups[f.name] ||= []
148:           radio_groups[f.name] << f 
149:         end
150:     
151:         # take one radio button from each group
152:         radio_groups.each_value do |g|
153:           checked = g.select {|f| f.checked}
154:     
155:           if checked.size == 1
156:             f = checked.first
157:             query.push(*f.query_value)
158:           elsif checked.size > 1 
159:             raise "multiple radiobuttons are checked in the same group!" 
160:           end
161:         end
162: 
163:         @clicked_buttons.each { |b|
164:           query.push(*b.query_value)
165:         }
166:     
167:         query
168:       end

Removes all fields with name field_name.

[Source]

     # File lib/www/mechanize/form.rb, line 196
196:       def delete_field!(field_name)
197:         @fields.delete_if{ |f| f.name == field_name}
198:       end

Fetch the first field whose name is equal to field_name

[Source]

    # File lib/www/mechanize/form.rb, line 65
65:       def field(field_name)
66:         fields.find { |f| f.name.eql? field_name }
67:       end

Returns whether or not the form contains a field with field_name

[Source]

    # File lib/www/mechanize/form.rb, line 50
50:       def has_field?(field_name)
51:         ! fields.find { |f| f.name.eql? field_name }.nil?
52:       end
has_key?(field_name)

Alias for has_field?

[Source]

    # File lib/www/mechanize/form.rb, line 56
56:       def has_value?(value)
57:         ! fields.find { |f| f.value.eql? value }.nil?
58:       end

[Source]

    # File lib/www/mechanize/form.rb, line 60
60:       def keys; fields.map { |f| f.name }; end

Treat form fields like accessors.

[Source]

     # File lib/www/mechanize/form.rb, line 117
117:       def method_missing(id,*args)
118:         method = id.to_s.gsub(/=$/, '')
119:         if field(method)
120:           return field(method).value if args.empty?
121:           return field(method).value = args[0]
122:         end
123:         super
124:       end

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,

[Source]

     # File lib/www/mechanize/form.rb, line 179
179:       def request_data
180:         query_params = build_query()
181:         case @enctype.downcase
182:         when 'multipart/form-data'
183:           boundary = rand_string(20)
184:           @enctype << "; boundary=#{boundary}"
185:           params = []
186:           query_params.each { |k,v| params << param_to_multipart(k, v) }
187:           @file_uploads.each { |f| params << file_to_multipart(f) }
188:           params.collect { |p| "--#{boundary}\r\n#{p}" }.join('') +
189:             "--#{boundary}--\r\n"
190:         else
191:           WWW::Mechanize.build_query_string(query_params)
192:         end
193:       end

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 an Array with the second value of the array 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 => ['bar', 1] )

[Source]

    # File lib/www/mechanize/form.rb, line 82
82:       def set_fields(fields = {})
83:         fields.each do |k,v|
84:           value = nil
85:           index = 0
86:           v.each do |val|
87:             index = val.to_i unless value.nil?
88:             value = val if value.nil?
89:           end
90:           self.fields.name(k.to_s).[](index).value = value
91:         end
92:       end

Submit this form with the button passed in

[Source]

     # File lib/www/mechanize/form.rb, line 127
127:       def submit(button=nil)
128:         @mech.submit(self, button)
129:       end

[Source]

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

Private Instance methods

[Source]

     # File lib/www/mechanize/form.rb, line 265
265:       def file_to_multipart(file)
266:         file_name = file.file_name ? ::File.basename(file.file_name) : ''
267:         body =  "Content-Disposition: form-data; name=\"" +
268:                 "#{mime_value_quote(file.name)}\"; " +
269:                 "filename=\"#{mime_value_quote(file_name)}\"\r\n" +
270:                 "Content-Transfer-Encoding: binary\r\n"
271: 
272:         if file.file_data.nil? and ! file.file_name.nil?
273:           file.file_data = ::File.open(file.file_name, "rb") { |f| f.read }
274:           file.mime_type = WEBrick::HTTPUtils.mime_type(file.file_name,
275:                                           WEBrick::HTTPUtils::DefaultMimeTypes)
276:         end
277: 
278:         if file.mime_type != nil
279:           body << "Content-Type: #{file.mime_type}\r\n"
280:         end
281:     
282:         body <<
283:           if file.file_data.respond_to? :read
284:             "\r\n#{file.file_data.read}\r\n"
285:           else
286:             "\r\n#{file.file_data}\r\n"
287:           end
288: 
289:         body
290:       end

[Source]

     # File lib/www/mechanize/form.rb, line 255
255:       def mime_value_quote(str)
256:         str.gsub(/(["\r\\])/){|s| '\\' + s}
257:       end

[Source]

     # File lib/www/mechanize/form.rb, line 259
259:       def param_to_multipart(name, value)
260:         return "Content-Disposition: form-data; name=\"" +
261:                 "#{mime_value_quote(name)}\"\r\n" +
262:                 "\r\n#{value}\r\n"
263:       end

[Source]

     # File lib/www/mechanize/form.rb, line 201
201:       def parse
202:         @fields       = WWW::Mechanize::List.new
203:         @buttons      = WWW::Mechanize::List.new
204:         @file_uploads = WWW::Mechanize::List.new
205:         @radiobuttons = WWW::Mechanize::List.new
206:         @checkboxes   = WWW::Mechanize::List.new
207:     
208:         # Find all input tags
209:         (form_node/'input').each do |node|
210:           type = (node['type'] || 'text').downcase
211:           name = node['name']
212:           next if name.nil? && !(type == 'submit' || type =='button')
213:           case type
214:           when 'radio'
215:             @radiobuttons << RadioButton.new(node['name'], node['value'], node.has_attribute?('checked'), self)
216:           when 'checkbox'
217:             @checkboxes << CheckBox.new(node['name'], node['value'], node.has_attribute?('checked'), self)
218:           when 'file'
219:             @file_uploads << FileUpload.new(node['name'], nil) 
220:           when 'submit'
221:             @buttons << Button.new(node['name'], node['value'])
222:           when 'button'
223:             @buttons << Button.new(node['name'], node['value'])
224:           when 'image'
225:             @buttons << ImageButton.new(node['name'], node['value'])
226:           else
227:             @fields << Field.new(node['name'], node['value'] || '') 
228:           end
229:         end
230: 
231:         # Find all textarea tags
232:         (form_node/'textarea').each do |node|
233:           next if node['name'].nil?
234:           @fields << Field.new(node['name'], node.inner_text)
235:         end
236: 
237:         # Find all select tags
238:         (form_node/'select').each do |node|
239:           next if node['name'].nil?
240:           if node.has_attribute? 'multiple'
241:             @fields << MultiSelectList.new(node['name'], node)
242:           else
243:             @fields << SelectList.new(node['name'], node)
244:           end
245:         end
246:       end

[Source]

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

[Validate]