class Merb::Helpers::Form::Builder::Base

Public Class Methods

new(obj, name, origin) click to toggle source
# File lib/merb-helpers/form/builder.rb, line 10
def initialize(obj, name, origin)
  @obj, @origin = obj, origin
  @name = name || @obj.class.name.snake_case.split("/").last
end

Public Instance Methods

bound_check_box(method, attrs = {}) click to toggle source
# File lib/merb-helpers/form/builder.rb, line 45
def bound_check_box(method, attrs = {})
  name = control_name(method)
  update_bound_controls(method, attrs, "checkbox")
  unbound_check_box({:name => name}.merge(attrs))
end
bound_radio_button(method, attrs = {}) click to toggle source
# File lib/merb-helpers/form/builder.rb, line 62
def bound_radio_button(method, attrs = {})
  name = control_name(method)
  update_bound_controls(method, attrs, "radio")
  unbound_radio_button({:name => name, :value => control_value(method)}.merge(attrs))
end
bound_radio_group(method, arr) click to toggle source
# File lib/merb-helpers/form/builder.rb, line 73
def bound_radio_group(method, arr)
  val = control_value(method)
  arr.map do |attrs|
    attrs = {:value => attrs} unless attrs.is_a?(Hash)
    attrs[:checked] = true if (val == attrs[:value])
    radio_group_item(method, attrs)
  end.join
end
bound_select(method, attrs = {}) click to toggle source
# File lib/merb-helpers/form/builder.rb, line 91
def bound_select(method, attrs = {})
  name = control_name(method)
  update_bound_controls(method, attrs, "select")
  unbound_select({:name => name}.merge(attrs))
end
bound_text_area(method, attrs = {}) click to toggle source
# File lib/merb-helpers/form/builder.rb, line 103
def bound_text_area(method, attrs = {})
  name = "#{@name}[#{method}]"
  update_bound_controls(method, attrs, "text_area")
  unbound_text_area(control_value(method), {:name => name}.merge(attrs))
end
button(contents, attrs) click to toggle source
# File lib/merb-helpers/form/builder.rb, line 114
def button(contents, attrs)
  update_unbound_controls(attrs, "button")
  tag(:button, contents, attrs)
end
fieldset(attrs, &blk) click to toggle source
# File lib/merb-helpers/form/builder.rb, line 21
def fieldset(attrs, &blk)
  legend = (l_attr = attrs.delete(:legend)) ? tag(:legend, l_attr) : ""
  tag(:fieldset, legend + @origin.capture(&blk), attrs)
  # @origin.concat(contents, blk.binding)
end
form(attrs = {}, &blk) click to toggle source
# File lib/merb-helpers/form/builder.rb, line 15
def form(attrs = {}, &blk)
  captured = @origin.capture(&blk)
  fake_method_tag = process_form_attrs(attrs)
  tag(:form, fake_method_tag + captured, attrs)
end
submit(value, attrs) click to toggle source
# File lib/merb-helpers/form/builder.rb, line 119
def submit(value, attrs)
  attrs[:type]  ||= "submit"
  attrs[:name]  ||= "form_submit"
  attrs[:value] ||= value
  update_unbound_controls(attrs, "submit")
  self_closing_tag(:input, attrs)
end
unbound_check_box(attrs) click to toggle source
# File lib/merb-helpers/form/builder.rb, line 51
def unbound_check_box(attrs)
  update_unbound_controls(attrs, "checkbox")
  if attrs.delete(:boolean)
    on, off = attrs.delete(:on), attrs.delete(:off)
    unbound_hidden_field(:name => attrs[:name], :value => off) <<
      self_closing_tag(:input, {:type => "checkbox", :value => on}.merge(attrs))
  else
    self_closing_tag(:input, {:type => "checkbox"}.merge(attrs))
  end
end
unbound_radio_button(attrs) click to toggle source
# File lib/merb-helpers/form/builder.rb, line 68
def unbound_radio_button(attrs)
  update_unbound_controls(attrs, "radio")
  self_closing_tag(:input, {:type => "radio"}.merge(attrs))
end
unbound_radio_group(arr, attrs = {}) click to toggle source
# File lib/merb-helpers/form/builder.rb, line 82
def unbound_radio_group(arr, attrs = {})
  arr.map do |ind_attrs|
    ind_attrs = {:value => ind_attrs} unless ind_attrs.is_a?(Hash)
    joined = attrs.merge(ind_attrs)
    joined.merge!(:label => joined[:label] || joined[:value])
    unbound_radio_button(joined)
  end.join
end
unbound_select(attrs = {}) click to toggle source
# File lib/merb-helpers/form/builder.rb, line 97
def unbound_select(attrs = {})
  update_unbound_controls(attrs, "select")
  attrs[:name] << "[]" if attrs[:multiple] && !(attrs[:name] =~ /\[\]$/)
  tag(:select, options_for(attrs), attrs)
end
unbound_text_area(contents, attrs) click to toggle source
# File lib/merb-helpers/form/builder.rb, line 109
def unbound_text_area(contents, attrs)
  update_unbound_controls(attrs, "text_area")
  tag(:textarea, contents, attrs)
end

Private Instance Methods

add_css_class(attrs, new_class) click to toggle source
# File lib/merb-helpers/form/builder.rb, line 295
def add_css_class(attrs, new_class)
  attrs[:class] = attrs[:class] ? "#{attrs[:class]} #{new_class}" : new_class
end
considered_true?(value) click to toggle source
# File lib/merb-helpers/form/builder.rb, line 278
def considered_true?(value)
  value && value != "false" && value != "0" && value != 0
end
control_name(method) click to toggle source
# File lib/merb-helpers/form/builder.rb, line 282
def control_name(method)
  @obj ? "#{@name}[#{method}]" : method
end
control_value(method) click to toggle source
# File lib/merb-helpers/form/builder.rb, line 286
def control_value(method)
  value = @obj ? @obj.send(method) : @origin.params[method]
  if Merb.disabled?(:merb_helper_escaping)
    value.to_s
  else
    Merb::Parse.escape_xml(value.to_s)
  end
end
fake_out_method(attrs, method) click to toggle source

This can be overridden to use another method to fake out methods

# File lib/merb-helpers/form/builder.rb, line 144
def fake_out_method(attrs, method)
  unbound_hidden_field(:name => "_method", :value => method)
end
options(col, text_meth, value_meth, sel, b = nil) click to toggle source
# File lib/merb-helpers/form/builder.rb, line 250
def options(col, text_meth, value_meth, sel, b = nil)
  ([b] + col.map do |item|
    text_meth = text_meth && item.respond_to?(text_meth) ? text_meth : :last
    value_meth = value_meth && item.respond_to?(value_meth) ? value_meth : :first

    text  = item.is_a?(String) ? item : item.send(text_meth)
    value = item.is_a?(String) ? item : item.send(value_meth)
    
    unless Merb.disabled?(:merb_helper_escaping)
      text  = Merb::Parse.escape_xml(text)
      value = Merb::Parse.escape_xml(value)
    end

    option_attrs = {:value => value}
    if sel.is_a?(Array)
      option_attrs.merge!(:selected => "selected") if value.in? sel.map {|e| e.to_s }
    else
      option_attrs.merge!(:selected => "selected") if value == sel.to_s
    end
    tag(:option, text, option_attrs)
  end).join
end
options_for(attrs) click to toggle source

Accepts a collection (hash, array, enumerable, your type) and returns a string of option tags. Given a collection where the elements respond to first and last (such as a two-element array), the “lasts” serve as option values and the “firsts” as option text. Hashes are turned into this form automatically, so the keys become “firsts” and values become lasts. If selected is specified, the matching “last” or element will get the selected option-tag. Selected may also be an array of values to be selected when using a multiple select.

Parameters

attrs<Hash>

HTML attributes and options

Options

selected

The value of a selected object, which may be either a string or an array.

prompt

Adds an addtional option tag with the provided string with no value.

include_blank

Adds an additional blank option tag with no value.

Returns

String

HTML

Examples

<%= options_for [["apple", "Apple Pie"], ["orange", "Orange Juice"]], :selected => "orange"
=> <option value="apple">Apple Pie</option><option value="orange" selected="selected">Orange Juice</option>

<%= options_for [["apple", "Apple Pie"], ["orange", "Orange Juice"]], :selected => ["orange", "apple"], :prompt => "Select One"
=> <option value="">Select One</option><option value="apple" selected="selected">Apple Pie</option><option value="orange" selected="selected">Orange Juice</option>
# File lib/merb-helpers/form/builder.rb, line 232
def options_for(attrs)
  blank, prompt = attrs.delete(:include_blank), attrs.delete(:prompt)
  b = blank || prompt ? tag(:option, prompt || "", :value => "") : ""

  # yank out the options attrs
  collection, selected, text_method, value_method = 
    attrs.extract!(:collection, :selected, :text_method, :value_method)

  # if the collection is a Hash, optgroups are a-coming
  if collection.is_a?(Hash)
    ([b] + collection.map do |g,col|
      tag(:optgroup, options(col, text_method, value_method, selected), :label => g)
    end).join
  else
    options(collection || [], text_method, value_method, selected, b)
  end
end
process_form_attrs(attrs) click to toggle source
# File lib/merb-helpers/form/builder.rb, line 129
def process_form_attrs(attrs)
  method = attrs[:method]

  # Unless the method is :get, fake out the method using :post
  attrs[:method] = :post unless attrs[:method] == :get
  # Use a fake PUT if the object is not new, otherwise use the method
  # passed in. Defaults to :post if no method is set.
  method ||= (@obj.respond_to?(:new_record?) && !@obj.new_record?) ? :put : :post

  attrs[:enctype] = "multipart/form-data" if attrs.delete(:multipart) || @multipart

  method == :post || method == :get ? "" : fake_out_method(attrs, method)
end
radio_group_item(method, attrs) click to toggle source
# File lib/merb-helpers/form/builder.rb, line 273
def radio_group_item(method, attrs)
  attrs.merge!(:checked => "checked") if attrs[:checked]
  bound_radio_button(method, attrs)
end
update_bound_check_box(method, attrs) click to toggle source
# File lib/merb-helpers/form/builder.rb, line 157
def update_bound_check_box(method, attrs)
  raise ArgumentError, ":value can't be used with a bound_check_box" if attrs.has_key?(:value)

  attrs[:boolean] = attrs.fetch(:boolean, true)

  val = control_value(method)
  attrs[:checked] = attrs.key?(:on) ? val == attrs[:on] : considered_true?(val)
end
update_bound_controls(method, attrs, type) click to toggle source
# File lib/merb-helpers/form/builder.rb, line 148
def update_bound_controls(method, attrs, type)
  case type
  when "checkbox"
    update_bound_check_box(method, attrs)
  when "select"
    update_bound_select(method, attrs)
  end
end
update_bound_select(method, attrs) click to toggle source
# File lib/merb-helpers/form/builder.rb, line 166
def update_bound_select(method, attrs)
  attrs[:value_method] ||= method
  attrs[:text_method] ||= attrs[:value_method] || :to_s
  attrs[:selected] ||= control_value(method)
end
update_unbound_check_box(attrs) click to toggle source
# File lib/merb-helpers/form/builder.rb, line 185
def update_unbound_check_box(attrs)
  boolean = attrs[:boolean] || (attrs[:on] && attrs[:off]) ? true : false

  case
  when attrs.key?(:on) ^ attrs.key?(:off)
    raise ArgumentError, ":on and :off must be specified together"
  when (attrs[:boolean] == false) && (attrs.key?(:on))
    raise ArgumentError, ":boolean => false cannot be used with :on and :off"
  when boolean && attrs.key?(:value)
    raise ArgumentError, ":value can't be used with a boolean checkbox"
  end

  if attrs[:boolean] = boolean
    attrs[:on] ||= "1"; attrs[:off] ||= "0"
  end

  attrs[:checked] = "checked" if attrs.delete(:checked)
end
update_unbound_controls(attrs, type) click to toggle source
# File lib/merb-helpers/form/builder.rb, line 172
def update_unbound_controls(attrs, type)
  case type
  when "checkbox"
    update_unbound_check_box(attrs)
  when "radio"
    update_unbound_radio_button(attrs)
  when "file"
    @multipart = true
  end

  attrs[:disabled] ? attrs[:disabled] = "disabled" : attrs.delete(:disabled)
end
update_unbound_radio_button(attrs) click to toggle source
# File lib/merb-helpers/form/builder.rb, line 204
def update_unbound_radio_button(attrs)
  attrs[:checked] = "checked" if attrs.delete(:checked)
end