# Form helpers provide a number of methods to simplify the creation of HTML forms.
# They can work directly with models (bound) or standalone (unbound).
#
# The core method of this helper, +form_for+, gives you the ability to create a form for a resource.
# For example, let's say that you have a model Person and want to create a new instance of it:
module Merb::Helpers::Form
def _singleton_form_context
@_singleton_form_context ||=
self._form_class.new(nil, nil, self)
end
def form_contexts
@_form_contexts ||= []
end
def current_form_context
form_contexts.last || _singleton_form_context
end
def _new_form_context(name, builder)
if name.is_a?(String) || name.is_a?(Symbol)
ivar = instance_variable_get("@#{name}")
else
ivar, name = name, name.class.to_s.snake_case
end
builder ||= current_form_context.class if current_form_context
(builder || self._form_class).new(ivar, name, self)
end
def with_form_context(name, builder)
form_contexts.push(_new_form_context(name, builder))
ret = yield
form_contexts.pop
ret
end
# Generates a form tag, which accepts a block that is not directly based on resource attributes
#
# ==== Parameters
# attrs:: HTML attributes
#
# ==== Returns
# String:: HTML
#
# ==== Notes
# * Block helpers use the <%= =%> syntax
# * a multipart enctype is automatically set if the form contains a file upload field
#
# ==== Example
# <%= form :action => url(:controller => "foo", :action => "bar", :id => 1) do %>
# <%= text_field :name => "first_name", :label => "First Name" %>
# <%= submit "Create" %>
# <% end =%>
#
# Generates the HTML:
#
#
def form(*args, &blk)
_singleton_form_context.form(*args, &blk)
end
# Generates a resource specific form tag which accepts a block, this also provides automatic resource routing.
#
# ==== Parameters
# name:: Model or Resource
# attrs:: HTML attributes
#
# ==== Returns
# String:: HTML
#
# ==== Notes
# * Block helpers use the <%= =%> syntax
#
# ==== Example
# <%= form_for @person do %>
# <%= text_field :first_name, :label => "First Name" %>
# <%= text_field :last_name, :label => "Last Name" %>
# <%= submit "Create" %>
# <% end =%>
#
# The HTML generated for this would be:
#
#
def form_for(name, attrs = {}, &blk)
with_form_context(name, attrs.delete(:builder)) do
current_form_context.form(attrs, &blk)
end
end
# Creates a scope around a specific resource object like form_for, but doesnt create the form tags themselves.
# This makes fields_for suitable for specifying additional resource objects in the same form.
#
# ==== Examples
# <%= form_for @person do %>
# <%= text_field :first_name, :label => "First Name" %>
# <%= text_field :last_name, :label => "Last Name" %>
# <% fields_for :permission do %>
# <%= check_box :is_admin, :label => "Administrator" %>
# <% end %>
# <%= submit "Create" %>
# <% end =%>
def fields_for(name, attrs = {}, &blk)
attrs ||= {}
with_form_context(name, attrs.delete(:builder)) do
current_form_context.concat(attrs, &blk)
end
end
# Provides the ability to create quick fieldsets as blocks for your forms.
#
# ==== Parameters
# attrs:: HTML attributes and options
#
# ==== Options
# +legend+:: Adds a legend tag within the fieldset
#
# ==== Returns
# String:: HTML
#
# ==== Notes
# Block helpers use the <%= =%> syntax
#
# ==== Example
# <%= fieldset :legend => "Customer Options" do %>
# ...your form elements
# <% end =%>
#
# Generates the HTML:
#
#
def fieldset(attrs = {}, &blk)
_singleton_form_context.fieldset(attrs, &blk)
end
def fieldset_for(name, attrs = {}, &blk)
with_form_context(name, attrs.delete(:builder)) do
current_form_context.fieldset(attrs, &blk)
end
end
# Provides a HTML text input tag
#
# ==== Parameters
# name:: Model or Resource
# attrs:: HTML attributes
#
# ==== Returns
# String:: HTML
#
# ==== Example
# <%= text_field :name => :fav_color, :label => "Your Favorite Color" %>
# # =>
#
# Used with a model:
#
# <%= form_for @person do %>
# <%= text_field :first_name, :label => "First Name" %>
# <% end =%>
def text_field; end
# Provides a HTML password input.
#
# ==== Parameters
# name:: Model or Resource
# attrs:: HTML attributes
#
# ==== Returns
# String:: HTML
#
# ==== Example
# <%= password_field :name => :password, :label => "Password" %>
# # =>
#
# Used with a model:
#
# <%= password_field :password, :label => 'New Password' %>
def password_field; end
# Provides a HTML hidden input field
#
# ==== Parameters
# name:: Model or Resource
# attrs:: HTML attributes
#
# ==== Returns
# String:: HTML
#
# ==== Example
# <%= hidden_field :name => "secret", :value => "some secret value" %>
#
# Used with a model:
#
# <%= hidden_field :identifier %>
# # =>
def hidden_field; end
# Provides a HTML file input
#
# ==== Parameters
# name:: Model or Resource
# attrs:: HTML attributes
#
# ==== Returns
# String:: HTML
#
# ==== Example
# <%= file_field :name => "file", :label => "File" %>
#
# Used with a model:
#
# <%= file_field :file, :label => "Choose a file" %>
def file_field; end
# Provides a HTML textarea tag
#
# ==== Parameters
# contents:: Contents of the text area
# attrs:: HTML attributes
#
# ==== Returns
# String:: HTML
#
# ==== Example
# <%= text_area "my comments", :name => "comments" %>
#
# Used with a model:
#
# <%= text_area :comments %>
def text_area; end
# Provides a HTML select
#
# ==== Parameters
# method:: Resource attribute
# attrs:: HTML attributes and options
#
# ==== Options
# +prompt+:: Adds an additional option tag with the provided string with no value.
# +selected+:: The value of a selected object, which may be either a string or an array.
# +include_blank+:: Adds an additional blank option tag with no value.
# +collection+:: The collection for the select options
# +text_method+:: Method to determine text of an option (as a symbol). Ex: :text_method => :name will call .name on your record object for what text to display.
# +value_method+:: Method to determine value of an option (as a symbol).
#
# ==== Returns
# String:: HTML
#
# ==== Example
# <%= select :name, :collection => %w(one two three) %>
def select; end
# Provides a generic HTML checkbox input tag.
# There are two ways this tag can be generated, based on the
# option :boolean. If not set to true, a "magic" input is generated.
# Otherwise, an input is created that can be easily used for passing
# an array of values to the application.
#
# ==== Parameters
# method:: Resource attribute
# attrs:: HTML attributes and options
#
# ==== Returns
# String:: HTML
#
# ==== Example
# <%= check_box :name => "is_activated", :value => "1" %>
# <%= check_box :name => "choices[]", :boolean => false, :value => "dog" %>
# <%= check_box :name => "choices[]", :boolean => false, :value => "cat" %>
# <%= check_box :name => "choices[]", :boolean => false, :value => "weasle" %>
#
# Used with a model:
#
# <%= check_box :is_activated, :label => "Activated?" %>
def check_box; end
# Provides a HTML radio input tag
#
# ==== Parameters
# method:: Resource attribute
# attrs:: HTML attributes and options
#
# ==== Returns
# String:: HTML
#
# ==== Example
# <%= radio_button :name => "radio_options", :value => "1", :label => "One" %>
# <%= radio_button :name => "radio_options", :value => "2", :label => "Two" %>
# <%= radio_button :name => "radio_options", :value => "3", :label => "Three", :checked => true %>
#
# Used with a model:
#
# <%= form_for @person do %>
# <%= radio_button :first_name %>
# <% end =%>
def radio_button; end
# Provides a radio group based on a resource attribute.
# This is generally used within a resource block such as +form_for+.
#
# ==== Parameters
# method:: Resource attribute
# arr:: Choices
#
# ==== Returns
# String:: HTML
#
# ==== Examples
# <%# the labels are the options %>
# <%= radio_group :my_choice, [5,6,7] %>
#
# <%# custom labels %>
# <%= radio_group :my_choice, [{:value => 5, :label => "five"}] %>
def radio_group; end
# @todo radio_group helper still needs to be implemented
%w(text_field password_field hidden_field file_field
text_area select check_box radio_button radio_group).each do |kind|
self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
def #{kind}(*args)
if bound?(*args)
current_form_context.bound_#{kind}(*args)
else
current_form_context.unbound_#{kind}(*args)
end
end
RUBY
end
# Generates a HTML button.
#
# ==== Parameters
# contents:: HTML contained within the button tag
# attrs:: HTML attributes
#
# ==== Returns
# String:: HTML
#
# ==== Notes
# * Buttons do not always work as planned in IE
# http://www.peterbe.com/plog/button-tag-in-IE
# * Not all mobile browsers support buttons
# http://nickcowie.com/2007/time-to-stop-using-the-button-element/
#
# ==== Example
# <%= button "Initiate Launch Sequence" %>
def button(contents, attrs = {})
current_form_context.button(contents, attrs)
end
# Generates a HTML submit button.
#
# ==== Parameters
# value:: Sets the value="" attribute
# attrs:: HTML attributes
#
# ==== Returns
# String:: HTML
#
# ==== Example
# <%= submit "Process" %>
def submit(contents, attrs = {})
current_form_context.submit(contents, attrs)
end
# Provides a HTML formatted display of resource errors in an unordered list with a h2 form submission error
#
# ==== Parameters
# obj:: Model or Resource
# error_class:: CSS class to use for error container
# build_li:: Custom li tag to wrap each error in
# header:: Custom header text for the error container
# before:: Display the errors before or inside of the form
#
# ==== Returns
# String:: HTML
#
# ==== Examples
# <%= error_messages_for :person %>
# <%= error_messages_for :person {|errors| "You can has probs nao: #{errors.size} of em!"}
# <%= error_messages_for :person, lambda{|error| "