Class: Mechanize::Form
- Inherits:
-
Object
- Object
- Mechanize::Form
- Extended by:
- Forwardable, ElementMatcher
- Defined in:
- lib/mechanize/form.rb
Overview
This class encapsulates a form parsed out of an HTML page. Each type of input field available in a form can be accessed through this object.
Examples
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']
Defined Under Namespace
Classes: Button, CheckBox, Field, FileUpload, Hidden, ImageButton, Keygen, MultiSelectList, Option, RadioButton, Reset, SelectList, Submit, Text, Textarea
Constant Summary collapse
- CRLF =
"\r\n".freeze
Instance Attribute Summary collapse
-
#action ⇒ Object
Returns the value of attribute action.
-
#buttons ⇒ Object
readonly
Returns the value of attribute buttons.
-
#checkboxes ⇒ Object
readonly
Returns the value of attribute checkboxes.
-
#encoding ⇒ Object
Character encoding of form data (i.e. UTF-8).
-
#enctype ⇒ Object
Content-Type for form data (i.e. application/x-www-form-urlencoded).
-
#fields ⇒ Object
(also: #elements)
readonly
Returns the value of attribute fields.
-
#file_uploads ⇒ Object
readonly
Returns the value of attribute file_uploads.
-
#ignore_encoding_error ⇒ Object
When true, character encoding errors will never be never raised on form submission.
-
#method ⇒ Object
Returns the value of attribute method.
-
#name ⇒ Object
Returns the value of attribute name.
-
#node ⇒ Object
(also: #form_node)
readonly
:method: at_xpath.
-
#page ⇒ Object
readonly
Returns the value of attribute page.
-
#radiobuttons ⇒ Object
readonly
Returns the value of attribute radiobuttons.
Instance Method Summary collapse
-
#[](field_name) ⇒ Object
Fetch the value of the first input field with the name passed in.
-
#[]=(field_name, value) ⇒ Object
Set the value of the first input field with the name passed in.
-
#add_button_to_query(button) ⇒ Object
This method adds a button to the query.
-
#add_field!(field_name, value = nil) ⇒ Object
Add a field with
field_name
andvalue
. -
#build_query(buttons = []) ⇒ Object
This method builds an array of arrays that represent the query parameters to be used with this form.
-
#button ⇒ Object
:method: buttons_with(criteria).
-
#checkbox ⇒ Object
:method: checkboxes_with(criteria).
-
#click_button(button = buttons.first) ⇒ Object
Submit form using
button
. -
#delete_field!(field_name) ⇒ Object
Removes all fields with name
field_name
. -
#dom_class ⇒ Object
This method is a shortcut to get form’s DOM class.
-
#dom_id ⇒ Object
This method is a shortcut to get form’s DOM id.
-
#field ⇒ Object
:method: fields_with(criteria).
-
#file_upload ⇒ Object
:method: file_uploads_with(criteria).
-
#has_field?(field_name) ⇒ Boolean
(also: #has_key?)
Returns whether or not the form contains a field with
field_name
. -
#has_value?(value) ⇒ Boolean
Returns whether or not the form contains a field with
value
. -
#hidden_field?(field_name) ⇒ Boolean
Returns whether or not the form contains a Hidden field named
field_name
. -
#hiddens ⇒ Object
Returns all fields of type Hidden.
-
#initialize(node, mech = nil, page = nil) ⇒ Form
constructor
A new instance of Form.
-
#keygens ⇒ Object
Returns all fields of type Keygen.
-
#keys ⇒ Object
Returns all field names (keys) for this form.
-
#method_missing(meth, *args) ⇒ Object
Treat form fields like accessors.
-
#pretty_print(q) ⇒ Object
:nodoc:.
-
#radiobutton ⇒ Object
:method: radiobuttons_with(criteria).
-
#request_data ⇒ Object
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,.
-
#reset ⇒ Object
This method allows the same form to be submitted second time with the different submit button being clicked.
-
#reset_button?(button_name) ⇒ Boolean
Returns whether or not the form contains a Reset button named
button_name
. -
#resets ⇒ Object
Returns all buttons of type Reset.
-
#save_hash_field_order ⇒ Object
This method adds an index to all fields that have Hash nodes.
-
#set_fields(fields = {}) ⇒ Object
This method sets multiple fields on the form.
-
#submit(button = nil, headers = {}) ⇒ Object
Submit the form.
-
#submit_button?(button_name) ⇒ Boolean
Returns whether or not the form contains a Submit button named
button_name
. -
#submits ⇒ Object
Returns all buttons of type Submit.
-
#text_field?(field_name) ⇒ Boolean
Returns whether or not the form contains a Text field named
field_name
. -
#textarea_field?(field_name) ⇒ Boolean
Returns whether or not the form contains a Textarea named
field_name
. -
#textareas ⇒ Object
Returns all fields of type Textarea.
-
#texts ⇒ Object
Returns all fields of type Text.
-
#values ⇒ Object
Returns all field values for this form.
Methods included from ElementMatcher
Constructor Details
#initialize(node, mech = nil, page = nil) ⇒ Form
Returns a new instance of Form.
43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/mechanize/form.rb', line 43 def initialize(node, mech = nil, page = nil) @enctype = node['enctype'] || 'application/x-www-form-urlencoded' @node = node @action = Mechanize::Util.html_unescape(node['action']) @method = (node['method'] || 'GET').upcase @name = node['name'] @clicked_buttons = [] @page = page @mech = mech @encoding = node['accept-charset'] || (page && page.encoding) || nil @ignore_encoding_error = false parse end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(meth, *args) ⇒ Object
Treat form fields like accessors.
258 259 260 261 262 263 264 265 266 267 |
# File 'lib/mechanize/form.rb', line 258 def method_missing(meth, *args) (method = meth.to_s).chomp!('=') if field(method) return field(method).value if args.empty? return field(method).value = args[0] end super end |
Instance Attribute Details
#action ⇒ Object
Returns the value of attribute action.
23 24 25 |
# File 'lib/mechanize/form.rb', line 23 def action @action end |
#buttons ⇒ Object (readonly)
Returns the value of attribute buttons.
25 26 27 |
# File 'lib/mechanize/form.rb', line 25 def @buttons end |
#checkboxes ⇒ Object (readonly)
Returns the value of attribute checkboxes.
25 26 27 |
# File 'lib/mechanize/form.rb', line 25 def checkboxes @checkboxes end |
#encoding ⇒ Object
Character encoding of form data (i.e. UTF-8)
31 32 33 |
# File 'lib/mechanize/form.rb', line 31 def encoding @encoding end |
#enctype ⇒ Object
Content-Type for form data (i.e. application/x-www-form-urlencoded)
28 29 30 |
# File 'lib/mechanize/form.rb', line 28 def enctype @enctype end |
#fields ⇒ Object (readonly) Also known as: elements
Returns the value of attribute fields.
25 26 27 |
# File 'lib/mechanize/form.rb', line 25 def fields @fields end |
#file_uploads ⇒ Object (readonly)
Returns the value of attribute file_uploads.
25 26 27 |
# File 'lib/mechanize/form.rb', line 25 def file_uploads @file_uploads end |
#ignore_encoding_error ⇒ Object
When true, character encoding errors will never be never raised on form submission. Default is false
35 36 37 |
# File 'lib/mechanize/form.rb', line 35 def ignore_encoding_error @ignore_encoding_error end |
#method ⇒ Object
Returns the value of attribute method.
23 24 25 |
# File 'lib/mechanize/form.rb', line 23 def method @method end |
#name ⇒ Object
Returns the value of attribute name.
23 24 25 |
# File 'lib/mechanize/form.rb', line 23 def name @name end |
#node ⇒ Object (readonly) Also known as: form_node
:method: at_xpath
Shorthand for node.at_xpath
.
See also Nokogiri::XML::Node#at_xpath for details.
198 199 200 |
# File 'lib/mechanize/form.rb', line 198 def node @node end |
#page ⇒ Object (readonly)
Returns the value of attribute page.
41 42 43 |
# File 'lib/mechanize/form.rb', line 41 def page @page end |
#radiobuttons ⇒ Object (readonly)
Returns the value of attribute radiobuttons.
25 26 27 |
# File 'lib/mechanize/form.rb', line 25 def @radiobuttons end |
Instance Method Details
#[](field_name) ⇒ Object
Fetch the value of the first input field with the name passed in. Example:
puts form['name']
241 242 243 244 |
# File 'lib/mechanize/form.rb', line 241 def [](field_name) f = field(field_name) f && f.value end |
#[]=(field_name, value) ⇒ Object
Set the value of the first input field with the name passed in. Example:
form['name'] = 'Aaron'
248 249 250 251 252 253 254 255 |
# File 'lib/mechanize/form.rb', line 248 def []=(field_name, value) f = field(field_name) if f f.value = value else add_field!(field_name, value) end end |
#add_button_to_query(button) ⇒ Object
This method adds a button to the query. If the form needs to be submitted with multiple buttons, pass each button to this method.
370 371 372 373 374 375 376 377 378 379 380 |
# File 'lib/mechanize/form.rb', line 370 def () unless .node.document == @node.document then = "#{.inspect} does not belong to the same page as " \ "the form #{@name.inspect} in #{@page.uri}" raise ArgumentError, end @clicked_buttons << end |
#add_field!(field_name, value = nil) ⇒ Object
Add a field with field_name
and value
201 202 203 |
# File 'lib/mechanize/form.rb', line 201 def add_field!(field_name, value = nil) fields << Field.new({'name' => field_name}, value) end |
#build_query(buttons = []) ⇒ Object
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.
300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 |
# File 'lib/mechanize/form.rb', line 300 def build_query( = []) query = [] @mech.log.info("form encoding: #{encoding}") if @mech && @mech.log save_hash_field_order successful_controls = [] (fields + checkboxes).reject do |f| f.node["disabled"] || f.node["name"] == "" end.sort.each do |f| case f when Mechanize::Form::CheckBox if f.checked successful_controls << f end when Mechanize::Form::Field successful_controls << f end end radio_groups = {} .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(&:checked) if checked.uniq.size > 1 then values = checked.map(&:value).join(', ').inspect name = checked.first.name.inspect raise Mechanize::Error, "radiobuttons #{values} are checked in the #{name} group, " \ "only one is allowed" else successful_controls << checked.first unless checked.empty? end end @clicked_buttons.each { |b| successful_controls << b } successful_controls.sort.each do |ctrl| # DOM order qval = proc_query(ctrl) query.push(*qval) end query end |
#button ⇒ Object
:method: buttons_with(criteria)
Find all buttons that match criteria
Example:
form.(:value => /submit/).each do ||
.value = 'hello!'
end
475 |
# File 'lib/mechanize/form.rb', line 475 elements_with :button |
#checkbox ⇒ Object
:method: checkboxes_with(criteria)
Find all checkboxes that match criteria
Example:
form.checkboxes_with(:name => /woo/).each do |field|
field.check
end
547 |
# File 'lib/mechanize/form.rb', line 547 elements_with :checkbox, :checkboxes |
#click_button(button = buttons.first) ⇒ Object
Submit form using button
. Defaults to the first button.
277 278 279 |
# File 'lib/mechanize/form.rb', line 277 def ( = .first) submit() end |
#delete_field!(field_name) ⇒ Object
Removes all fields with name field_name
.
425 426 427 |
# File 'lib/mechanize/form.rb', line 425 def delete_field!(field_name) @fields.delete_if{ |f| f.name == field_name} end |
#dom_class ⇒ Object
This method is a shortcut to get form’s DOM class. Common usage:
page.form_with(:dom_class => "foorm")
Note that you can also use :class
to get to this method:
page.form_with(:class => "foorm")
However, attribute values are compared literally as string, so form_with(class: “a”) does not match a form with class=“a b”. Use form_with(css: “form.a”) instead.
152 153 154 |
# File 'lib/mechanize/form.rb', line 152 def dom_class @node['class'] end |
#dom_id ⇒ Object
This method is a shortcut to get form’s DOM id. Common usage:
page.form_with(:dom_id => "foorm")
Note that you can also use :id
to get to this method:
page.form_with(:id => "foorm")
140 141 142 |
# File 'lib/mechanize/form.rb', line 140 def dom_id @node['id'] end |
#field ⇒ Object
:method: fields_with(criteria)
Find all fields that match criteria
Example:
form.fields_with(:value => /foo/).each do |field|
field.value = 'hello!'
end
451 |
# File 'lib/mechanize/form.rb', line 451 elements_with :field |
#file_upload ⇒ Object
:method: file_uploads_with(criteria)
Find all file upload fields that match criteria
Example:
form.file_uploads_with(:file_name => /picutre/).each do |field|
field.value = 'foo!'
end
499 |
# File 'lib/mechanize/form.rb', line 499 elements_with :file_upload |
#has_field?(field_name) ⇒ Boolean Also known as: has_key?
Returns whether or not the form contains a field with field_name
59 60 61 |
# File 'lib/mechanize/form.rb', line 59 def has_field?(field_name) fields.any? { |f| f.name == field_name } end |
#has_value?(value) ⇒ Boolean
Returns whether or not the form contains a field with value
66 67 68 |
# File 'lib/mechanize/form.rb', line 66 def has_value?(value) fields.any? { |f| f.value == value } end |
#hidden_field?(field_name) ⇒ Boolean
Returns whether or not the form contains a Hidden field named field_name
126 127 128 |
# File 'lib/mechanize/form.rb', line 126 def hidden_field?(field_name) hiddens.find { |f| f.name == field_name } end |
#hiddens ⇒ Object
Returns all fields of type Hidden
96 97 98 |
# File 'lib/mechanize/form.rb', line 96 def hiddens @hiddens ||= fields.select { |f| f.class == Hidden } end |
#keygens ⇒ Object
Returns all fields of type Keygen
106 107 108 |
# File 'lib/mechanize/form.rb', line 106 def keygens @keygens ||= fields.select { |f| f.class == Keygen } end |
#keys ⇒ Object
Returns all field names (keys) for this form
71 72 73 |
# File 'lib/mechanize/form.rb', line 71 def keys fields.map(&:name) end |
#pretty_print(q) ⇒ Object
:nodoc:
549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 |
# File 'lib/mechanize/form.rb', line 549 def pretty_print(q) # :nodoc: q.object_group(self) { q.breakable; q.group(1, '{name', '}') { q.breakable; q.pp name } q.breakable; q.group(1, '{method', '}') { q.breakable; q.pp method } q.breakable; q.group(1, '{action', '}') { q.breakable; q.pp action } q.breakable; q.group(1, '{fields', '}') { fields.each do |field| q.breakable q.pp field end } q.breakable; q.group(1, '{radiobuttons', '}') { .each { |b| q.breakable; q.pp b } } q.breakable; q.group(1, '{checkboxes', '}') { checkboxes.each { |b| q.breakable; q.pp b } } q.breakable; q.group(1, '{file_uploads', '}') { file_uploads.each { |b| q.breakable; q.pp b } } q.breakable; q.group(1, '{buttons', '}') { .each { |b| q.breakable; q.pp b } } } end |
#radiobutton ⇒ Object
:method: radiobuttons_with(criteria)
Find all radio buttons that match criteria
Example:
form.(:name => /woo/).each do |field|
field.check
end
523 |
# File 'lib/mechanize/form.rb', line 523 elements_with :radiobutton |
#request_data ⇒ Object
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,
394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 |
# File 'lib/mechanize/form.rb', line 394 def request_data query_params = build_query() case @enctype.downcase when /^multipart\/form-data/ boundary = rand_string(20) @enctype = "multipart/form-data; boundary=#{boundary}" delimiter = "--#{boundary}\r\n" data = ::String.new query_params.each do |k,v| if k data << delimiter param_to_multipart(k, v, data) end end @file_uploads.each do |f| data << delimiter file_to_multipart(f, data) end data << "--#{boundary}--\r\n" else Mechanize::Util.build_query_string(query_params) end end |
#reset ⇒ Object
This method allows the same form to be submitted second time with the different submit button being clicked.
384 385 386 387 |
# File 'lib/mechanize/form.rb', line 384 def reset # In the future, should add more functionality here to reset the form values to their defaults. @clicked_buttons = [] end |
#reset_button?(button_name) ⇒ Boolean
Returns whether or not the form contains a Reset button named button_name
116 117 118 |
# File 'lib/mechanize/form.rb', line 116 def () resets.find { |f| f.name == } end |
#resets ⇒ Object
Returns all buttons of type Reset
86 87 88 |
# File 'lib/mechanize/form.rb', line 86 def resets @resets ||= .select { |f| f.class == Reset } end |
#save_hash_field_order ⇒ Object
This method adds an index to all fields that have Hash nodes. This enables field sorting to maintain order.
357 358 359 360 361 362 363 364 365 366 |
# File 'lib/mechanize/form.rb', line 357 def save_hash_field_order index = 0 fields.each do |field| if Hash === field.node field.index = index index += 1 end end end |
#set_fields(fields = {}) ⇒ Object
This method sets multiple fields on the form. It takes a list of fields
which are 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' }
218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 |
# File 'lib/mechanize/form.rb', line 218 def set_fields fields = {} fields.each do |name, v| case v when Hash v.each do |index, value| self.fields_with(:name => name.to_s)[index].value = value end else value = nil index = 0 [v].flatten.each do |val| index = val.to_i if value value = val unless value end self.fields_with(:name => name.to_s)[index].value = value end end end |
#submit(button = nil, headers = {}) ⇒ Object
Submit the form. Does not include the button
as a form parameter. Use click_button
or provide button as a parameter.
271 272 273 |
# File 'lib/mechanize/form.rb', line 271 def submit = nil, headers = {} @mech.submit(self, , headers) end |
#submit_button?(button_name) ⇒ Boolean
Returns whether or not the form contains a Submit button named button_name
111 112 113 |
# File 'lib/mechanize/form.rb', line 111 def () submits.find { |f| f.name == } end |
#submits ⇒ Object
Returns all buttons of type Submit
81 82 83 |
# File 'lib/mechanize/form.rb', line 81 def submits @submits ||= .select { |f| f.class == Submit } end |
#text_field?(field_name) ⇒ Boolean
Returns whether or not the form contains a Text field named field_name
121 122 123 |
# File 'lib/mechanize/form.rb', line 121 def text_field?(field_name) texts.find { |f| f.name == field_name } end |
#textarea_field?(field_name) ⇒ Boolean
Returns whether or not the form contains a Textarea named field_name
131 132 133 |
# File 'lib/mechanize/form.rb', line 131 def textarea_field?(field_name) textareas.find { |f| f.name == field_name } end |
#textareas ⇒ Object
Returns all fields of type Textarea
101 102 103 |
# File 'lib/mechanize/form.rb', line 101 def textareas @textareas ||= fields.select { |f| f.class == Textarea } end |
#texts ⇒ Object
Returns all fields of type Text
91 92 93 |
# File 'lib/mechanize/form.rb', line 91 def texts @texts ||= fields.select { |f| f.class == Text } end |
#values ⇒ Object
Returns all field values for this form
76 77 78 |
# File 'lib/mechanize/form.rb', line 76 def values fields.map(&:value) end |