Class WWW::Mechanize::Form
In: lib/www/mechanize/form/button.rb
lib/www/mechanize/form/check_box.rb
lib/www/mechanize/form/field.rb
lib/www/mechanize/form/file_upload.rb
lib/www/mechanize/form/image_button.rb
lib/www/mechanize/form/multi_select_list.rb
lib/www/mechanize/form/option.rb
lib/www/mechanize/form/radio_button.rb
lib/www/mechanize/form/select_list.rb
lib/www/mechanize/form.rb
lib/www/mechanize/monkey_patch.rb
Parent: Object
Mechanize\n[lib/www/mechanize.rb\nlib/www/mechanize/chain.rb\nlib/www/mechanize/chain/auth_headers.rb\nlib/www/mechanize/chain/body_decoding_handler.rb\nlib/www/mechanize/chain/connection_resolver.rb\nlib/www/mechanize/chain/custom_headers.rb\nlib/www/mechanize/chain/header_resolver.rb\nlib/www/mechanize/chain/parameter_resolver.rb\nlib/www/mechanize/chain/pre_connect_hook.rb\nlib/www/mechanize/chain/request_resolver.rb\nlib/www/mechanize/chain/response_body_parser.rb\nlib/www/mechanize/chain/response_header_handler.rb\nlib/www/mechanize/chain/response_reader.rb\nlib/www/mechanize/chain/ssl_resolver.rb\nlib/www/mechanize/chain/uri_resolver.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_response.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/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/redirect_limit_reached_error.rb\nlib/www/mechanize/redirect_not_get_or_head_error.rb\nlib/www/mechanize/response_code_error.rb\nlib/www/mechanize/unsupported_scheme_error.rb\nlib/www/mechanize/util.rb] lib/www/mechanize.rb Handler WWW dot/m_52_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
pretty_inspect -> inspect

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           = Util.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 100
100:       def [](field_name)
101:         f = field(field_name)
102:         f && f.value
103:       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 109
109:       def []=(field_name, value)
110:         f = field(field_name)
111:         if f.nil?
112:           add_field!(field_name, value)
113:         else
114:           f.value = value
115:         end
116:       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 206
206:       def add_button_to_query(button)
207:         @clicked_buttons << button
208:       end

Add a field with field_name and value

[Source]

    # File lib/www/mechanize/form.rb, line 65
65:       def add_field!(field_name, value = nil)
66:         fields << Field.new(field_name, value)
67:       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 162
162:       def build_query(buttons = [])
163:         query = []
164:     
165:         fields().each do |f|
166:           qval = proc_query(f)
167:           query.push(*qval)
168:         end
169:     
170:         checkboxes().each do |f|
171:           if f.checked
172:             qval = proc_query(f)
173:             query.push(*qval)
174:           end
175:         end
176:     
177:         radio_groups = {}
178:         radiobuttons().each do |f|
179:           fname = from_native_charset(f.name)
180:           radio_groups[fname] ||= []
181:           radio_groups[fname] << f 
182:         end
183:     
184:         # take one radio button from each group
185:         radio_groups.each_value do |g|
186:           checked = g.select {|f| f.checked}
187:     
188:           if checked.size == 1
189:             f = checked.first
190:             qval = proc_query(f)
191:             query.push(*qval)
192:           elsif checked.size > 1 
193:             raise "multiple radiobuttons are checked in the same group!" 
194:           end
195:         end
196: 
197:         @clicked_buttons.each { |b|
198:           qval = proc_query(b)
199:           query.push(*qval)
200:         }
201:         query
202:       end

Submit form using button. Defaults to the first button.

[Source]

     # File lib/www/mechanize/form.rb, line 135
135:       def click_button(button = buttons.first)
136:         submit(button)
137:       end

Removes all fields with name field_name.

[Source]

     # File lib/www/mechanize/form.rb, line 230
230:       def delete_field!(field_name)
231:         @fields.delete_if{ |f| f.name == field_name}
232:       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 119
119:       def method_missing(id,*args)
120:         method = id.to_s.gsub(/=$/, '')
121:         if field(method)
122:           return field(method).value if args.empty?
123:           return field(method).value = args[0]
124:         end
125:         super
126:       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 213
213:       def request_data
214:         query_params = build_query()
215:         case @enctype.downcase
216:         when /^multipart\/form-data/
217:           boundary = rand_string(20)
218:           @enctype = "multipart/form-data; boundary=#{boundary}"
219:           params = []
220:           query_params.each { |k,v| params << param_to_multipart(k, v) unless k.nil? }
221:           @file_uploads.each { |f| params << file_to_multipart(f) }
222:           params.collect { |p| "--#{boundary}\r\n#{p}" }.join('') +
223:             "--#{boundary}--\r\n"
224:         else
225:           WWW::Mechanize::Util.build_query_string(query_params)
226:         end
227:       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 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' } )

[Source]

    # File lib/www/mechanize/form.rb, line 77
77:       def set_fields(fields = {})
78:         fields.each do |k,v|
79:           case v
80:           when Hash
81:             v.each do |index, value|
82:               self.fields_with(:name => k.to_s).[](index).value = value
83:             end
84:           else
85:             value = nil
86:             index = 0
87:             [v].flatten.each do |val|
88:               index = val.to_i unless value.nil?
89:               value = val if value.nil?
90:             end
91:             self.fields_with(:name => k.to_s).[](index).value = value
92:           end
93:         end
94:       end

Submit this form with the button passed in

[Source]

     # File lib/www/mechanize/form.rb, line 129
129:       def submit button=nil, headers = {}
130:         @mech.submit(self, button, headers)
131:       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 333
333:       def file_to_multipart(file)
334:         file_name = file.file_name ? ::File.basename(file.file_name) : ''
335:         body =  "Content-Disposition: form-data; name=\"" +
336:                 "#{mime_value_quote(file.name)}\"; " +
337:                 "filename=\"#{mime_value_quote(file_name)}\"\r\n" +
338:                 "Content-Transfer-Encoding: binary\r\n"
339: 
340:         if file.file_data.nil? and ! file.file_name.nil?
341:           file.file_data = ::File.open(file.file_name, "rb") { |f| f.read }
342:           file.mime_type = WEBrick::HTTPUtils.mime_type(file.file_name,
343:                                           WEBrick::HTTPUtils::DefaultMimeTypes)
344:         end
345: 
346:         if file.mime_type != nil
347:           body << "Content-Type: #{file.mime_type}\r\n"
348:         end
349:     
350:         body <<
351:           if file.file_data.respond_to? :read
352:             "\r\n#{file.file_data.read}\r\n"
353:           else
354:             "\r\n#{file.file_data}\r\n"
355:           end
356: 
357:         body
358:       end

[Source]

     # File lib/www/mechanize/form.rb, line 149
149:       def from_native_charset(str, enc=nil)
150:         if page
151:           enc ||= page.encoding
152:           Util.from_native_charset(str,enc)
153:         else
154:           str
155:         end
156:       end

[Source]

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

[Source]

     # File lib/www/mechanize/form.rb, line 327
327:       def param_to_multipart(name, value)
328:         return "Content-Disposition: form-data; name=\"" +
329:                 "#{mime_value_quote(name)}\"\r\n" +
330:                 "\r\n#{value}\r\n"
331:       end

[Source]

     # File lib/www/mechanize/form.rb, line 261
261:       def parse
262:         @fields       = []
263:         @buttons      = []
264:         @file_uploads = []
265:         @radiobuttons = []
266:         @checkboxes   = []
267:     
268:         # Find all input tags
269:         form_node.search('input').each do |node|
270:           type = (node['type'] || 'text').downcase
271:           name = node['name']
272:           next if name.nil? && !(type == 'submit' || type =='button')
273:           case type
274:           when 'radio'
275:             @radiobuttons << RadioButton.new(node['name'], node['value'], !!node['checked'], self)
276:           when 'checkbox'
277:             @checkboxes << CheckBox.new(node['name'], node['value'], !!node['checked'], self)
278:           when 'file'
279:             @file_uploads << FileUpload.new(node['name'], nil) 
280:           when 'submit'
281:             @buttons << Button.new(node['name'], node['value'])
282:           when 'button'
283:             @buttons << Button.new(node['name'], node['value'])
284:           when 'image'
285:             @buttons << ImageButton.new(node['name'], node['value'])
286:           else
287:             @fields << Field.new(node['name'], node['value'] || '') 
288:           end
289:         end
290: 
291:         # Find all textarea tags
292:         form_node.search('textarea').each do |node|
293:           next if node['name'].nil?
294:           @fields << Field.new(node['name'], node.inner_text)
295:         end
296: 
297:         # Find all select tags
298:         form_node.search('select').each do |node|
299:           next if node['name'].nil?
300:           if node.has_attribute? 'multiple'
301:             @fields << MultiSelectList.new(node['name'], node)
302:           else
303:             @fields << SelectList.new(node['name'], node)
304:           end
305:         end
306: 
307:         # Find all submit button tags
308:         # FIXME: what can I do with the reset buttons?
309:         form_node.search('button').each do |node|
310:           type = (node['type'] || 'submit').downcase
311:           next if type == 'reset'
312:           @buttons << Button.new(node['name'], node['value'])
313:         end
314:       end

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

[Source]

     # File lib/www/mechanize/form.rb, line 141
141:       def proc_query(field)
142:         return unless field.query_value
143:         field.query_value.map{|(name, val)| 
144:           [from_native_charset(name), from_native_charset(val.to_s)]
145:         }
146:       end

[Source]

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

[Validate]