class ActionView::Helpers::FormBuilder

def self._to_partial_path

def self._to_partial_path
  @_to_partial_path ||= name.demodulize.underscore.sub!(/_builder$/, "")
end

def button(value = nil, options = {}, &block)


#
# Save as draft
# =>
# Create post
# =>
# Ask me!
# =>
button(:draft, value: true)

# =>
button("Create post")
==== Examples

create: "Add %{model}"
post:
submit:
helpers:
en:

It also searches for a key specific to the given object:

update: "Confirm changes to %{model}"
create: "Create a %{model}"
submit:
helpers:
en:

(the same as submit helper) and using %{model} for translation interpolation:
Those labels can be customized using I18n under the +helpers.submit+ key

button label; otherwise, it uses "Update Post".
In the example above, if @post is a new record, it will use "Create Post" as

<% end %>
<%= f.button %>
<%= form_for @post do |f| %>

if the object is a new resource or not to create the proper label:
Add the submit button for the given form. When no value is given, it checks
def button(value = nil, options = {}, &block)
  case value
  when Hash
    value, options = nil, value
  when Symbol
    value, options = nil, { name: field_name(value), id: field_id(value) }.merge!(options.to_h)
  end
  value ||= submit_default_value
  if block_given?
    value = @template.capture { yield(value) }
  end
  formmethod = options[:formmethod]
  if formmethod.present? && !/post|get/i.match?(formmethod) && !options.key?(:name) && !options.key?(:value)
    options.merge! formmethod: :post, name: "_method", value: formmethod
  end
  @template.button_tag(value, options)
end

def check_box(method, options = {}, checked_value = "1", unchecked_value = "0")

#
# =>
check_box("accepted", { class: 'eula_check' }, "yes", "no")
# Let's say that @eula.accepted is "no":

#
# =>
check_box("gooddog", {}, "yes", "no")
# Let's say that @puppy.gooddog is "no":

#
# =>
check_box("validated")
# Let's say that @post.validated? is 1:

==== Examples

hashes instead of arrays.
In that case it is preferable to either use +check_box_tag+ or to use

get an extra ghost item with only that attribute, assigned to "0".
the elements of the array. For each item with a checked check box you
because parameter name repetition is precisely what \Rails seeks to distinguish

<% end %>
...
<%= form.check_box :paid %>
<%= fields_for "project[invoice_attributes][]", invoice, index: nil do |form| %>

within an array-like parameter, as in
Unfortunately that workaround does not work when the check box goes

key in the query string, that works for ordinary forms.
form, and parameters extraction gets the last occurrence of any repeated
says key/value pairs have to be sent in the same order they appear in the
the check box is unchecked), or both fields. Since the HTML specification
This way, the client either sends only the hidden field (representing

attributes mimic an unchecked check box.
every check box. The hidden field has the same name and its
To prevent this the helper generates an auxiliary hidden field before

wouldn't update the flag.

@invoice.update(params[:invoice])

any mass-assignment idiom like
invoice the user unchecks its check box, no +paid+ parameter is sent. So,
if an +Invoice+ model has a +paid+ flag, and in the form that edits a paid
thus web browsers do not send them. Unfortunately this introduces a gotcha:
The HTML specification says unchecked check boxes are not successful, and

==== Gotcha

* :include_hidden - If set to false, the auxiliary hidden field described below will not be generated.
* :checked - +true+ or +false+ forces the state of the checkbox to be checked or not.
* Any standard HTML attributes for the tag can be passed in, for example +:class+.

==== Options

while the default +unchecked_value+ is set to 0 which is convenient for boolean values.
Additional options on the input tag can be passed as a hash with +options+. The +checked_value+ defaults to 1
It's intended that +method+ returns an integer and if that integer is above zero, then the checkbox is checked.
assigned to the template (identified by +object+). This object must be an instance object (@object) and not a local object.
Returns a checkbox tag tailored for accessing a specified attribute (identified by +method+) on an object
def check_box(method, options = {}, checked_value = "1", unchecked_value = "0")
  @template.check_box(@object_name, method, objectify_options(options), checked_value, unchecked_value)
end

def collection_check_boxes(method, collection, value_method, text_method, options = {}, html_options = {}, &block)

Please refer to the documentation of the base helper for details.

<% end %>
<%= f.submit %>
<%= f.collection_check_boxes :author_ids, Author.all, :id, :name_with_initial %>
<%= form_for @post do |f| %>

Wraps ActionView::Helpers::FormOptionsHelper#collection_check_boxes for form builders:
def collection_check_boxes(method, collection, value_method, text_method, options = {}, html_options = {}, &block)
  @template.collection_check_boxes(@object_name, method, collection, value_method, text_method, objectify_options(options), @default_html_options.merge(html_options), &block)
end

def collection_radio_buttons(method, collection, value_method, text_method, options = {}, html_options = {}, &block)

Please refer to the documentation of the base helper for details.

<% end %>
<%= f.submit %>
<%= f.collection_radio_buttons :author_id, Author.all, :id, :name_with_initial %>
<%= form_for @post do |f| %>

Wraps ActionView::Helpers::FormOptionsHelper#collection_radio_buttons for form builders:
def collection_radio_buttons(method, collection, value_method, text_method, options = {}, html_options = {}, &block)
  @template.collection_radio_buttons(@object_name, method, collection, value_method, text_method, objectify_options(options), @default_html_options.merge(html_options), &block)
end

def collection_select(method, collection, value_method, text_method, options = {}, html_options = {})

Please refer to the documentation of the base helper for details.

<% end %>
<%= f.submit %>
<%= f.collection_select :person_id, Author.all, :id, :name_with_initial, prompt: true %>
<%= form_for @post do |f| %>

Wraps ActionView::Helpers::FormOptionsHelper#collection_select for form builders:
def collection_select(method, collection, value_method, text_method, options = {}, html_options = {})
  @template.collection_select(@object_name, method, collection, value_method, text_method, objectify_options(options), @default_html_options.merge(html_options))
end

def convert_to_legacy_options(options)

def convert_to_legacy_options(options)
  if options.key?(:skip_id)
    options[:include_id] = !options.delete(:skip_id)
  end
end

def date_select(method, options = {}, html_options = {})

Please refer to the documentation of the base helper for details.

<% end %>
<%= f.submit %>
<%= f.date_select :birth_date %>
<%= form_for @person do |f| %>

Wraps ActionView::Helpers::DateHelper#date_select for form builders:
def date_select(method, options = {}, html_options = {})
  @template.date_select(@object_name, method, objectify_options(options), html_options)
end

def datetime_select(method, options = {}, html_options = {})

Please refer to the documentation of the base helper for details.

<% end %>
<%= f.submit %>
<%= f.datetime_select :last_request_at %>
<%= form_for @person do |f| %>

Wraps ActionView::Helpers::DateHelper#datetime_select for form builders:
def datetime_select(method, options = {}, html_options = {})
  @template.datetime_select(@object_name, method, objectify_options(options), html_options)
end

def emitted_hidden_id? # :nodoc:

:nodoc:
def emitted_hidden_id? # :nodoc:
  @emitted_hidden_id ||= nil
end

def field_id(method, *suffixes, namespace: @options[:namespace], index: @options[:index])

case).
element, sharing a common id root (post_title, in this
aria-describedby attribute referencing the
the call to FormBuilder#text_field declares an
In the example above, the element built by

<% end %>
<%= tag.span("is blank", id: f.field_id(:title, :error) %>
<%= f.text_field :title, aria: { describedby: f.field_id(:title, :error) } %>
<%= f.label :title %>
<%= form_for @post do |f| %>

attribute name.
Return the value generated by the FormBuilder for the given

Generate an HTML id attribute value for the given field
def field_id(method, *suffixes, namespace: @options[:namespace], index: @options[:index])
  @template.field_id(@object_name, method, *suffixes, namespace: namespace, index: index)
end

def field_name(method, *methods, multiple: false, index: @options[:index])


<% end %>
<%# => %>
<%= f.text_field :tag, name: f.field_name(:tag, multiple: true) %>
<%= form_for @post do |f| %>

<% end %>
<%# => %>
<%= f.text_field :title, name: f.field_name(:title, :subtitle) %>
<%= form_for @post do |f| %>

attribute name.
Return the value generated by the FormBuilder for the given

field combination
Generate an HTML name attribute value for the given name and
def field_name(method, *methods, multiple: false, index: @options[:index])
  object_name = @options.fetch(:as) { @object_name }
  @template.field_name(object_name, method, *methods, index: index, multiple: multiple)
end

def fields(scope = nil, model: nil, **options, &block)

See the docs for the ActionView::Helpers::FormHelper#fields helper method.
def fields(scope = nil, model: nil, **options, &block)
  options[:allow_method_names_outside_object] = true
  options[:skip_default_ids] = !FormHelper.form_with_generates_ids
  convert_to_legacy_options(options)
  fields_for(scope || model, model, options, &block)
end

def fields_for(record_name, record_object = nil, fields_options = nil, &block)

to prevent fields_for from rendering it automatically.
hidden field is not needed and you can pass include_id: false
to store the ID of the record. There are circumstances where this
Note that fields_for will automatically generate a hidden field

<% end %>
...
<% end %>
...
Project #<%= project_fields.index %>
<%= person_form.fields_for :projects do |project_fields| %>
...
<%= form_for @person do |person_form| %>

is available in the FormBuilder object.
object in the array. For this purpose, the index method
When a collection is used you might want to know the index of each

<% end %>
...
<% end %>
Delete: <%= project_fields.check_box :_destroy %>
<%= person_form.fields_for :projects do |project_fields| %>
...
<%= form_for @person do |person_form| %>

(e.g. 1, '1', true, or 'true'):
parameter with a value that evaluates to +true+
attributes hash by adding a form element for the _destroy
This will allow you to specify which models to destroy in the

end
accepts_nested_attributes_for :projects, allow_destroy: true
has_many :projects
class Person < ActiveRecord::Base

option for +accepts_nested_attributes_for+:
form, you have to enable it first using the :allow_destroy
If you want to destroy any of the associated models through the

<% end %>
...
<% end %>
Name: <%= project_fields.text_field :name %>
<%= person_form.fields_for :projects, @active_projects do |project_fields| %>
...
<%= form_for @person do |person_form| %>

Or a collection to be used:

<% end %>
...
<% end %>
<% end %>
<% end %>
Name: <%= project_fields.text_field :name %>
<%= person_form.fields_for :projects, project do |project_fields| %>
<% if project.active? %>
<% @person.projects.each do |project| %>
...
<%= form_for @person do |person_form| %>

It's also possible to specify the instance to be used:

<% end %>
...
<% end %>
<% end %>
Name: <%= project_fields.text_field :name %>
<% if project_fields.object.active? %>
<%= person_form.fields_for :projects do |project_fields| %>
...
<%= form_for @person do |person_form| %>

collection:
the nested fields_for call will be repeated for each instance in the
This model can now be used with a nested fields_for. The block given to

end
accepts_nested_attributes_for :projects
has_many :projects
class Person < ActiveRecord::Base

+accepts_nested_attributes_for+ to define the writer method for you:
When projects is already an association on Person you can use

collection, and the correct indices to be set in the form markup.
required for fields_for to correctly identify :projects as a
Note that the projects_attributes= writer method is in fact

end
end
# Process the attributes hash
def projects_attributes=(attributes)

end
[@project1, @project2]
def projects
class Person

projects_attributes= writer method:
from the projects reader method and responds to the
Consider a Person class which returns an _array_ of Project instances

==== One-to-many

<% end %>
...
<% end %>
Delete: <%= address_fields.check_box :_destroy %>
...
<%= person_form.fields_for :address do |address_fields| %>
...
<%= form_for @person do |person_form| %>

model (e.g. 1, '1', true, or 'true'):
with a value that evaluates to +true+, you will destroy the associated
Now, when you use a form element with the _destroy parameter,

end
accepts_nested_attributes_for :address, allow_destroy: true
has_one :address
class Person < ActiveRecord::Base

+accepts_nested_attributes_for+:
to enable it first using the :allow_destroy option for
If you want to destroy the associated model through the form, you have

end
accepts_nested_attributes_for :address
has_one :address
class Person < ActiveRecord::Base

+accepts_nested_attributes_for+ to define the writer method for you:
When address is already an association on a Person you can use

<% end %>
...
<% end %>
Zip code: <%= address_fields.text_field :zip_code %>
Street : <%= address_fields.text_field :street %>
<%= person_form.fields_for :address do |address_fields| %>
...
<%= form_for @person do |person_form| %>

This model can now be used with a nested fields_for, like so:

end
end
# Process the attributes hash
def address_attributes=(attributes)

end
@address
def address
class Person

address_attributes= writer method:
address reader method and responds to the
Consider a Person class which returns a _single_ Address from the

==== One-to-one

or an _array_ of objects.
depends on whether the normal reader method returns a _single_ object
Whether a one-to-one or one-to-many style form builder will be yielded

address_attributes=.
writer for the association :address is called
defining a method with the proper name. For example: the attribute
with +accepts_nested_attributes_for+ in a model definition or by
association. The most common way of defining these writers is either
Nested attribute writers are normal setter methods named after an

the attributes of a parent object and its associations in one go.
for that attribute. This allows you to create forms that set or change
writer for a certain attribute, fields_for will yield a new scope
When the object belonging to the current scope has a nested attribute

=== Nested Attributes Examples

<% end %>
...
<% end %>
Admin?: <%= check_box_tag permission_fields.field_name(:admin), @person.permission[:admin] %>
<%= fields_for :permission, @person.permission, {} do |permission_fields| %>
...
<%= form_for @person do |person_form| %>

option Hash. To remove the ambiguity, explicitly pass an option Hash, even if empty.
name and value parameters are provided and the provided value has the shape of an
+fields_for+ tries to be smart about parameters, but it can be confused if both

FormOptionsHelper#collection_select and DateHelper#datetime_select.
DateHelper that are designed to work with an object as base, like
Note: This also works for the methods in FormOptionsHelper and

of class +Permission+, the field will still be named permission[admin].
_class_ of the model object, e.g. if @person.permission, is
and +fields_for+ will derive the required name of the field from the

<% end %>
Admin?: <%= permission_fields.check_box :admin %>
<%= fields_for @person.permission do |permission_fields| %>

name has been omitted) -
argument isn't a string or symbol +fields_for+ will realize that the
Alternatively, you can pass just the model object itself (if the first

field will reflect the value of that variable's attribute @permission.admin.
instance variable @permission, the initial state of the input
...in which case, if :permission also happens to be the name of an

<% end %>
Admin?: <%= permission_fields.check_box :admin %>
<%= fields_for :permission do |permission_fields| %>

object to +fields_for+ -
Often this can be simplified by passing just the name of the model

reflect the value of @person.permission.admin.
+admin+, the initial state of the checkbox when first displayed will
If @person.permission is an existing record with an attribute
value will appear in the controller as params[:permission][:admin].
tag with the +name+ attribute permission[admin], and the submitted
In this case, the checkbox field will be represented by an HTML +input+

<% end %>
<%= person_form.submit %>

<% end %>
Admin? : <%= permission_fields.check_box :admin %>
<%= fields_for :permission, @person.permission do |permission_fields| %>

Last name : <%= person_form.text_field :last_name %>
First name: <%= person_form.text_field :first_name %>
<%= form_for @person do |person_form| %>

object itself can be passed to the method separately -
both an object name (represented by either a symbol or string) and the
displayed. In order for both of these features to be specified independently,
default values are shown when the form the fields appear in is first
values appear within the +params+ hash in the controller) and what
a model object in two ways - how they are named (hence how submitted
generate fields associated with the model object. Fields may reflect
and within the block allows methods to be called on the builder to
a FormBuilder object associated with a particular model object to a block,
its method signature is slightly different. Like +form_for+, it yields
Although the usage and purpose of +fields_for+ is similar to +form_for+'s,

for specifying additional model objects in the same form.
doesn't create the form tags themselves. This makes fields_for suitable
Creates a scope around a specific model object like form_for, but
def fields_for(record_name, record_object = nil, fields_options = nil, &block)
  fields_options, record_object = record_object, nil if fields_options.nil? && record_object.is_a?(Hash) && record_object.extractable_options?
  fields_options ||= {}
  fields_options[:builder] ||= options[:builder]
  fields_options[:namespace] = options[:namespace]
  fields_options[:parent_builder] = self
  case record_name
  when String, Symbol
    if nested_attributes_association?(record_name)
      return fields_for_with_nested_attributes(record_name, record_object, fields_options, block)
    end
  else
    record_object = @template._object_for_form_builder(record_name)
    record_name   = model_name_from_record_or_class(record_object).param_key
  end
  object_name = @object_name
  index = if options.has_key?(:index)
    options[:index]
  elsif defined?(@auto_index)
    object_name = object_name.to_s.delete_suffix("[]")
    @auto_index
  end
  record_name = if index
    "#{object_name}[#{index}][#{record_name}]"
  elsif record_name.end_with?("[]")
    "#{object_name}[#{record_name[0..-3]}][#{record_object.id}]"
  else
    "#{object_name}[#{record_name}]"
  end
  fields_options[:child_index] = index
  @template.fields_for(record_name, record_object, fields_options, &block)
end

def fields_for_nested_model(name, object, fields_options, block)

def fields_for_nested_model(name, object, fields_options, block)
  object = convert_to_model(object)
  emit_hidden_id = object.persisted? && fields_options.fetch(:include_id) {
    options.fetch(:include_id, true)
  }
  @template.fields_for(name, object, fields_options) do |f|
    output = @template.capture(f, &block)
    output.concat f.hidden_field(:id) if output && emit_hidden_id && !f.emitted_hidden_id?
    output
  end
end

def fields_for_with_nested_attributes(association_name, association, options, block)

def fields_for_with_nested_attributes(association_name, association, options, block)
  name = "#{object_name}[#{association_name}_attributes]"
  association = convert_to_model(association)
  if association.respond_to?(:persisted?)
    association = [association] if @object.public_send(association_name).respond_to?(:to_ary)
  elsif !association.respond_to?(:to_ary)
    association = @object.public_send(association_name)
  end
  if association.respond_to?(:to_ary)
    explicit_child_index = options[:child_index]
    output = ActiveSupport::SafeBuffer.new
    association.each do |child|
      if explicit_child_index
        options[:child_index] = explicit_child_index.call if explicit_child_index.respond_to?(:call)
      else
        options[:child_index] = nested_child_index(name)
      end
      if content = fields_for_nested_model("#{name}[#{options[:child_index]}]", child, options, block)
        output << content
      end
    end
    output
  elsif association
    fields_for_nested_model(name, association, options, block)
  end
end

def file_field(method, options = {})

# =>
file_field(:file, class: 'file_input')
# Let's say that @attachment has file:

# =>
file_field(:image, accept: 'image/png,image/gif,image/jpeg')
# Let's say that @post has image:

# =>
file_field(:attached, accept: 'text/html')
# Let's say that @post has attached:

# =>
file_field(:image, :multiple => true)
# Let's say that @post has image:

# =>
file_field(:avatar)
# Let's say that @user has avatar:
==== Examples

* :accept - If set to one or multiple mime-types, the user will be suggested a filter when choosing a file. You still need to set up model validations.
* :include_hidden - When multiple: true and include_hidden: true, the field will be prefixed with an field with an empty value to support submitting an empty collection of files. Since include_hidden will default to config.active_storage.multiple_file_field_include_hidden if you don't specify include_hidden, you will need to pass include_hidden: false to prevent submitting an empty collection of files when passing multiple: true.
* :multiple - If set to true, *in most updated browsers* the user will be allowed to select multiple files.
* :disabled - If set to true, the user will not be able to use this input.
* Creates standard HTML attributes for the tag.
==== Options

Using this method inside a +form_with+ block will set the enclosing form's encoding to multipart/form-data.

shown.
hash with +options+. These options will be tagged onto the HTML as an HTML element attribute as in the example
assigned to the template (identified by +object+). Additional options on the input tag can be passed as a
Returns a file upload input tag tailored for accessing a specified attribute (identified by +method+) on an object
def file_field(method, options = {})
  self.multipart = true
  @template.file_field(@object_name, method, objectify_options(options))
end

def grouped_collection_select(method, collection, group_method, group_label_method, option_key_method, option_value_method, options = {}, html_options = {})

Please refer to the documentation of the base helper for details.

<% end %>
<%= f.submit %>
<%= f.grouped_collection_select :country_id, @continents, :countries, :name, :id, :name %>
<%= form_for @city do |f| %>

Wraps ActionView::Helpers::FormOptionsHelper#grouped_collection_select for form builders:
def grouped_collection_select(method, collection, group_method, group_label_method, option_key_method, option_value_method, options = {}, html_options = {})
  @template.grouped_collection_select(@object_name, method, collection, group_method, group_label_method, option_key_method, option_value_method, objectify_options(options), @default_html_options.merge(html_options))
end

def hidden_field(method, options = {})


# =>
hidden_field(:token)
# Let's say that @user.token returns "abcde":

# =>
hidden_field(:tag_list)
# Let's say that @post.tag_list returns "blog, ruby":

# =>
hidden_field(:pass_confirm)
# Let's say that @signup.pass_confirm returns true:
==== Examples

shown.
hash with +options+. These options will be tagged onto the HTML as an HTML element attribute as in the example
assigned to the template (identified by +object+). Additional options on the input tag can be passed as a
Returns a hidden input tag tailored for accessing a specified attribute (identified by +method+) on an object
def hidden_field(method, options = {})
  @emitted_hidden_id = true if method == :id
  @template.hidden_field(@object_name, method, objectify_options(options))
end

def id

element's submit button, regardless of where it exists in the DOM.
def id
  options.dig(:html, :id) || options[:id]
end

def initialize(object_name, object, template, options)

def initialize(object_name, object, template, options)
  @nested_child_index = {}
  @object_name, @object, @template, @options = object_name, object, template, options
  @default_options = @options ? @options.slice(:index, :namespace, :skip_default_ids, :allow_method_names_outside_object) : {}
  @default_html_options = @default_options.except(:skip_default_ids, :allow_method_names_outside_object)
  convert_to_legacy_options(@options)
  if @object_name&.end_with?("[]")
    if (object ||= @template.instance_variable_get("@#{@object_name[0..-3]}")) && object.respond_to?(:to_param)
      @auto_index = object.to_param
    else
      raise ArgumentError, "object[] naming but object param and @object var don't exist or don't respond to to_param: #{object.inspect}"
    end
  end
  @multipart = nil
  @index = options[:index] || options[:child_index]
end

def label(method, text = nil, options = {}, &block)

# =>
end
raw('Accept Terms.')
label(:terms) do

# =>
end
])
("error_label" if builder.object.errors.include?(:cost))
"cost_label",
content_tag(:span, builder.translation, class: [
label(:cost) do |builder|

# =>
end
content_tag(:span, builder.translation, class: "cost_label")
label(:cost) do |builder|

# =>
end
content_tag(:span, translation, class: "cost_label")
label(:cost) do |translation|

# =>
label(:privacy, "Public Post", value: "public")

# =>
label(:title, "A short title", class: "title_label")

# =>
label(:title, "A short title")

# =>
label(:cost)



cost: "Total cost"
post:
attributes:
activerecord:

(if you are using ActiveRecord):
Localization can also be based purely on the translation of the attribute-name

# =>
label(:body)

Which then will result in

body: "Write your entire text here"
post:
label:
helpers:

For example you can define the following in your locale (e.g. en.yml)
You can localize your labels based on model and attribute names.

# =>
label(:title)
==== Examples

target labels for radio_button tags (where the value is used in the ID of the input tag).
onto the HTML as an HTML element attribute as in the example shown, except for the :value option, which is designed to
Additional options on the label tag can be passed as a hash with +options+. These options will be tagged
is found in the current I18n locale (through helpers.label..) or you specify it explicitly.
assigned to the template (identified by +object+). The text of label will default to the attribute name unless a translation
Returns a label tag tailored for labelling an input field for a specified attribute (identified by +method+) on an object
def label(method, text = nil, options = {}, &block)
  @template.label(@object_name, method, text, objectify_options(options), &block)
end

def multipart=(multipart)

def multipart=(multipart)
  @multipart = multipart
  if parent_builder = @options[:parent_builder]
    parent_builder.multipart = multipart
  end
end

def nested_attributes_association?(association_name)

def nested_attributes_association?(association_name)
  @object.respond_to?("#{association_name}_attributes=")
end

def nested_child_index(name)

def nested_child_index(name)
  @nested_child_index[name] ||= -1
  @nested_child_index[name] += 1
end

def objectify_options(options)

def objectify_options(options)
  result = @default_options.merge(options)
  result[:object] = @object
  result
end

def radio_button(method, tag_value, options = {})

#
# =>
radio_button("receive_newsletter", "no")
radio_button("receive_newsletter", "yes")
# Let's say that @user.receive_newsletter returns "no":

#
# =>
radio_button("category", "java")
radio_button("category", "rails")
# Let's say that @post.category returns "rails":

+options+ hash. You may pass HTML options there as well.
To force the radio button to be checked pass checked: true in the

radio button will be checked.
assigned to the template (identified by +object+). If the current value of +method+ is +tag_value+ the
Returns a radio button tag for accessing a specified attribute (identified by +method+) on an object
def radio_button(method, tag_value, options = {})
  @template.radio_button(@object_name, method, tag_value, objectify_options(options))
end

def select(method, choices = nil, options = {}, html_options = {}, &block)

Please refer to the documentation of the base helper for details.

<% end %>
<%= f.submit %>
<%= f.select :person_id, Person.all.collect { |p| [ p.name, p.id ] }, include_blank: true %>
<%= form_for @post do |f| %>

Wraps ActionView::Helpers::FormOptionsHelper#select for form builders:
def select(method, choices = nil, options = {}, html_options = {}, &block)
  @template.select(@object_name, method, choices, objectify_options(options), @default_html_options.merge(html_options), &block)
end

def submit(value = nil, options = {})


create: "Add %{model}"
post:
submit:
helpers:
en:

It also searches for a key specific to the given object:

update: "Confirm changes to %{model}"
create: "Create a %{model}"
submit:
helpers:
en:

%{model} for translation interpolation:
Those labels can be customized using I18n under the +helpers.submit+ key and using

submit button label; otherwise, it uses "Update Post".
In the example above, if @post is a new record, it will use "Create Post" as

<% end %>
<%= f.submit %>
<%= form_for @post do |f| %>

if the object is a new resource or not to create the proper label:
Add the submit button for the given form. When no value is given, it checks
def submit(value = nil, options = {})
  value, options = nil, value if value.is_a?(Hash)
  value ||= submit_default_value
  @template.submit_tag(value, options)
end

def submit_default_value

def submit_default_value
  object = convert_to_model(@object)
  key    = object ? (object.persisted? ? :update : :create) : :submit
  model = if object.respond_to?(:model_name)
    object.model_name.human
  else
    @object_name.to_s.humanize
  end
  defaults = []
  # Object is a model and it is not overwritten by as and scope option.
  if object.respond_to?(:model_name) && object_name.to_s == model.downcase
    defaults << :"helpers.submit.#{object.model_name.i18n_key}.#{key}"
  else
    defaults << :"helpers.submit.#{object_name}.#{key}"
  end
  defaults << :"helpers.submit.#{key}"
  defaults << "#{key.to_s.humanize} #{model}"
  I18n.t(defaults.shift, model: model, default: defaults)
end

def time_select(method, options = {}, html_options = {})

Please refer to the documentation of the base helper for details.

<% end %>
<%= f.submit %>
<%= f.time_select :average_lap %>
<%= form_for @race do |f| %>

Wraps ActionView::Helpers::DateHelper#time_select for form builders:
def time_select(method, options = {}, html_options = {})
  @template.time_select(@object_name, method, objectify_options(options), html_options)
end

def time_zone_select(method, priority_zones = nil, options = {}, html_options = {})

Please refer to the documentation of the base helper for details.

<% end %>
<%= f.submit %>
<%= f.time_zone_select :time_zone, nil, include_blank: true %>
<%= form_for @user do |f| %>

Wraps ActionView::Helpers::FormOptionsHelper#time_zone_select for form builders:
def time_zone_select(method, priority_zones = nil, options = {}, html_options = {})
  @template.time_zone_select(@object_name, method, priority_zones, objectify_options(options), @default_html_options.merge(html_options))
end

def to_model

def to_model
  self
end

def to_partial_path

def to_partial_path
  self.class._to_partial_path
end

def weekday_select(method, options = {}, html_options = {})

Please refer to the documentation of the base helper for details.

<% end %>
<%= f.submit %>
<%= f.weekday_select :weekday, include_blank: true %>
<%= form_for @user do |f| %>

Wraps ActionView::Helpers::FormOptionsHelper#weekday_select for form builders:
def weekday_select(method, options = {}, html_options = {})
  @template.weekday_select(@object_name, method, objectify_options(options), @default_html_options.merge(html_options))
end