Class: Scrapetor::Form

Inherits:
Object
  • Object
show all
Defined in:
lib/scrapetor/form.rb

Overview

HTML form helper. Pulls fields + default values out of a ‘<form>` element, lets the caller override or add values, and submits via the right method/action.

doc  = Scrapetor::Fetcher.fetch("https://example.com/login")
form = Scrapetor::Form.new(doc.at_css("form#login"),
                           base_url: "https://example.com/login")
form["username"] = "alice"
form["password"] = "secret"
resp = form.submit                  # uses Scrapetor::Fetcher

Captures every named control’s default value (incl. <select> / <input type=hidden|checkbox|radio> / <textarea>); pre-loaded fields like CSRF tokens carry forward automatically. Buttons are NOT included unless explicitly set — the caller decides which submit button “fired”.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(form_node, base_url: nil, http: nil) ⇒ Form

Returns a new instance of Form.

Raises:

  • (ArgumentError)


25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/scrapetor/form.rb', line 25

def initialize(form_node, base_url: nil, http: nil)
  raise ArgumentError, "form_node is required" if form_node.nil?
  @form    = form_node
  @base    = base_url
  @http    = http
  @method  = (form_node["method"] || form_node[:method] || "GET").upcase
  @enctype = (form_node["enctype"] || form_node[:enctype] || "application/x-www-form-urlencoded").downcase
  raw_action = form_node["action"] || form_node[:action] || ""
  @action = if raw_action.empty?
              base_url
            elsif base_url
              begin
                URI.join(base_url, raw_action).to_s
              rescue URI::InvalidURIError
                raw_action
              end
            else
              raw_action
            end
  @fields = capture_defaults(form_node)
end

Instance Attribute Details

#actionObject (readonly)

Returns the value of attribute action.



23
24
25
# File 'lib/scrapetor/form.rb', line 23

def action
  @action
end

#enctypeObject (readonly)

Returns the value of attribute enctype.



23
24
25
# File 'lib/scrapetor/form.rb', line 23

def enctype
  @enctype
end

#fieldsObject (readonly)

Returns the value of attribute fields.



23
24
25
# File 'lib/scrapetor/form.rb', line 23

def fields
  @fields
end

#methodObject (readonly)

Returns the value of attribute method.



23
24
25
# File 'lib/scrapetor/form.rb', line 23

def method
  @method
end

Instance Method Details

#[](name) ⇒ Object



47
# File 'lib/scrapetor/form.rb', line 47

def [](name);            @fields[name.to_s]; end

#[]=(name, value) ⇒ Object



48
# File 'lib/scrapetor/form.rb', line 48

def []=(name, value);    @fields[name.to_s] = value.to_s; end

#delete(name) ⇒ Object



49
# File 'lib/scrapetor/form.rb', line 49

def delete(name);        @fields.delete(name.to_s); end

#merge!(hash) ⇒ Object



50
# File 'lib/scrapetor/form.rb', line 50

def merge!(hash);        hash.each { |k, v| self[k] = v }; self; end

#submit(extra: {}, **fetcher_opts) ⇒ Object



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/scrapetor/form.rb', line 59

def submit(extra: {}, **fetcher_opts)
  params = @fields.merge(extra.transform_keys(&:to_s))
  client = @http || Scrapetor::Fetcher
  case @method
  when "GET"
    url = append_query(@action, params)
    client.get(url, **fetcher_opts)
  when "POST"
    if @enctype.include?("multipart")
      client.post(@action, multipart: params, **fetcher_opts)
    else
      client.post(@action, form: params, **fetcher_opts)
    end
  else
    # PUT/PATCH/DELETE via form are non-standard but supported.
    verb = @method.downcase.to_sym
    client.send(verb, @action,
                body: URI.encode_www_form(params),
                **fetcher_opts.merge(
                  headers: (fetcher_opts[:headers] || {}).merge(
                    "Content-Type" => "application/x-www-form-urlencoded"
                  )
                ))
  end
end

#to_hObject

Returns the params Hash that would be submitted, with all the captured defaults plus user overrides. Useful for inspection before #submit fires the request.



55
56
57
# File 'lib/scrapetor/form.rb', line 55

def to_h
  @fields.dup
end