class HalClient::Form

A single [Dwolla HAL form](github.com/Dwolla/hal-forms). Instances of this class allow clients to complete and submit individual forms.

This is an incomplete implementation of the spec. Thus far it supports string and hidden fields with JSON encoding. Enhancements are requested.

Attributes

content_type[R]
fields[R]
hal_client[R]
method[R]
target_tmpl[R]

Public Class Methods

new(parsed_json, hal_client) click to toggle source

Initializes a newly created form

parsed_json - a Hash create by parsing the JSON. hal_client - the `HalClient` with which to submit the new form.

# File lib/hal_client/form.rb, line 19
def initialize(parsed_json, hal_client)
  @hal_client = hal_client
  @target_tmpl = extract_target_tmpl(parsed_json)
  @method = extract_method(parsed_json)
  @content_type = extract_content_type(parsed_json)
  @fields = extract_fields(parsed_json)
end

Public Instance Methods

submit(answers={}) click to toggle source

Returns the `HalClient::Representation` returned from submitting the form.

answers - `Hash` containing the answer key to submit. Keys are

the field names; values are the values to submit.
# File lib/hal_client/form.rb, line 38
def submit(answers={})
  if :get == method
    hal_client.get(target_url(answers))
  else
    hal_client.public_send(method, target_url(answers), body(answers), "Content-Type" => content_type)
  end
end
target_url(answers={}) click to toggle source

Returns the `Addressable::URI` to which this form is targeted

# File lib/hal_client/form.rb, line 29
def target_url(answers={})
  target_tmpl.expand(answers)
end

Protected Instance Methods

body(answers) click to toggle source
# File lib/hal_client/form.rb, line 85
def body(answers)
  case content_type
  when /json$/i
    build_json_body(answers)
  else
    raise NotImplementedError, "#{content_type} is not a supported content type"
  end
end
build_json_body(answers) click to toggle source
# File lib/hal_client/form.rb, line 94
def build_json_body(answers)
  fields.reduce({}) { |body_thus_far, field|
    json_inject_answer(body_thus_far, field.extract_answer(answers), field.path)
  }
end
extract_content_type(parsed_json) click to toggle source
# File lib/hal_client/form.rb, line 72
def extract_content_type(parsed_json)
  return nil if :get == method

  parsed_json
    .fetch("contentType") { raise  ArgumentError, "form doesn't specify a content type" }
end
extract_fields(parsed_json) click to toggle source
# File lib/hal_client/form.rb, line 79
def extract_fields(parsed_json)
  parsed_json
    .fetch("fields") { raise  ArgumentError, "form doesn't have a field member" }
    .map { |field_json| Field.new(field_json) }
end
extract_method(parsed_json) click to toggle source
# File lib/hal_client/form.rb, line 62
def extract_method(parsed_json)
  parsed_json
    .fetch("method")
    .downcase
    .to_sym

rescue KeyError
  raise ArgumentError, "form doesn't specify a method"
end
extract_target_tmpl(parsed_json) click to toggle source
# File lib/hal_client/form.rb, line 50
def extract_target_tmpl(parsed_json)
  tmpl_str = parsed_json
             .fetch("_links")
             .fetch("target")
             .fetch("href")

  Addressable::Template.new(tmpl_str)

rescue KeyError
  raise ArgumentError, "form has no target href"
end
json_inject_answer(body, answer, path) click to toggle source
# File lib/hal_client/form.rb, line 100
def json_inject_answer(body, answer, path)
  patch = Hana::Patch.new [
    { 'op' => 'add', 'path' => path, 'value' => answer }
  ]

  patch.apply(body)
end