module ActionView::Helpers::FormHelper

def _object_for_form_builder(object) # :nodoc:

:nodoc:
def _object_for_form_builder(object) # :nodoc:
  object.is_a?(Array) ? object.last : object
end

def apply_form_for_options!(object, options) # :nodoc:

:nodoc:
def apply_form_for_options!(object, options) # :nodoc:
  object = convert_to_model(object)
  as = options[:as]
  namespace = options[:namespace]
  action = object.respond_to?(:persisted?) && object.persisted? ? :edit : :new
  options[:html] ||= {}
  options[:html].reverse_merge!(
    class:  as ? "#{action}_#{as}" : dom_class(object, action),
    id:     (as ? [namespace, action, as] : [namespace, dom_id(object, action)]).compact.join("_").presence,
  )
end

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

#
# =>
check_box("eula", "accepted", { class: 'eula_check' }, "yes", "no")

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

#
# =>
check_box("post", "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(object_name, method, options = {}, checked_value = "1", unchecked_value = "0")
  Tags::CheckBox.new(object_name, method, self, checked_value, unchecked_value, options).render
end

def color_field(object_name, method, options = {})

# =>
color_field("car", "color")

Returns a text_field of type "color".
def color_field(object_name, method, options = {})
  Tags::ColorField.new(object_name, method, self, options).render
end

def date_field(object_name, method, options = {})


# =>
date_field("user", "born_on", min: "2014-05-20")

values for "min" and "max."
Alternatively, you can pass a String formatted as an ISO8601 date as the

# =>
date_field("user", "born_on", min: Date.today)

instances of Date or Time to the options hash.
You can create values for the "min" and "max" attributes by passing

# =>
date_field("user", "born_on", value: "1984-05-12")
@user.born_on = Date.new(1984, 1, 27)

by passing the "value" option explicitly, e.g.
of DateTime and ActiveSupport::TimeWithZone. You can still override that
on the object's value, which makes it behave as expected for instances
The default value is generated by trying to call +strftime+ with "%Y-%m-%d"

# =>
date_field("user", "born_on")

Returns a text_field of type "date".
def date_field(object_name, method, options = {})
  Tags::DateField.new(object_name, method, self, options).render
end

def datetime_field(object_name, method, options = {})


# =>
datetime_field("user", "born_on", min: "2014-05-20T00:00:00")

the values for "min" and "max."
Alternatively, you can pass a String formatted as an ISO8601 datetime as

# =>
datetime_field("user", "born_on", min: Date.today)

instances of Date or Time to the options hash.
You can create values for the "min" and "max" attributes by passing

# =>
datetime_field("user", "born_on")
@user.born_on = Date.new(1984, 1, 12)

of DateTime and ActiveSupport::TimeWithZone.
on the object's value, which makes it behave as expected for instances
The default value is generated by trying to call +strftime+ with "%Y-%m-%dT%T"

# =>
datetime_field("user", "born_on")

Returns a text_field of type "datetime-local".
def datetime_field(object_name, method, options = {})
  Tags::DatetimeLocalField.new(object_name, method, self, options).render
end

def default_form_builder_class

def default_form_builder_class
  builder = default_form_builder || ActionView::Base.default_form_builder
  builder.respond_to?(:constantize) ? builder.constantize : builder
end

def email_field(object_name, method, options = {})


# =>
email_field("user", "address")

Returns a text_field of type "email".
def email_field(object_name, method, options = {})
  Tags::EmailField.new(object_name, method, self, options).render
end

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

FormOptionsHelper#collection_select and DateHelper#datetime_select.
to work with an object as a base, like
Same goes for the methods in FormOptionsHelper and DateHelper designed

<% end %>
<%= check_box_tag "comment[all_caps]", "1", @comment.commenter.hulk_mode? %>
<%= text_area :commenter, :biography %>

<%= fields.text_field :body %>
<%= fields model: @comment do |fields| %>

from FormTagHelper:
match the stand-alone FormHelper methods and methods
While +form_with+ uses a FormBuilder object it's possible to mix and

=== Mixing with other form helpers

either the passed scope or the scope inferred from the :model.
or model is yielded, so any generated field names are prefixed with
Much like +form_with+ a FormBuilder instance associated with the scope

<% end %>
<% end %>
<%= fields.text_field :body %>
<%= form.fields :comment do |fields| %>

<%= form.text_field :title %>
<%= form_with model: @post do |form| %>
# Using +fields+ with +form_with+:

# =>
<% end %>
<%= fields.text_field :body %>
<%= fields model: Comment.new(body: "full bodied") do |fields| %>
# Using a model infers the scope and assigns field values:

# =>
<% end %>
<%= fields.text_field :body %>
<%= fields :comment do |fields| %>
# Using a scope prefixes the input field names:

except it doesn't output the form tags.
Like +form_with+ does with :scope or :model,
Scopes input fields with either an explicit scope or model.
def fields(scope = nil, model: nil, **options, &block)
  options = { allow_method_names_outside_object: true, skip_default_ids: !form_with_generates_ids }.merge!(options)
  if model
    model   = _object_for_form_builder(model)
    scope ||= model_name_from_record_or_class(model).param_key
  end
  builder = instantiate_builder(scope, model, options)
  capture(builder, &block)
end

def fields_for(record_name, record_object = nil, options = {}, &block)

rendering it automatically.
can pass include_id: false to prevent fields_for from
There are circumstances where this hidden field is not needed and you
to store the ID of the record if it responds to persisted?.
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 into 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

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, options = {}, &block)
  options = { model: record_object, allow_method_names_outside_object: false, skip_default_ids: false }.merge!(options)
  fields(record_name, **options, &block)
end

def file_field(object_name, method, options = {})

# =>
file_field(:attachment, :file, class: 'file_input')

# =>
file_field(:post, :image, accept: 'image/png,image/gif,image/jpeg')

# =>
file_field(:post, :attached, accept: 'text/html')

# =>
file_field(:post, :image, multiple: true)

# =>
file_field(:user, :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.
* :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_for+ 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(object_name, method, options = {})
  options = { include_hidden: multiple_file_field_include_hidden }.merge!(options)
  Tags::FileField.new(object_name, method, self, convert_direct_upload_option_to_url(options.dup)).render
end

def form_for(record, options = {}, &block)

<% end %>
...
<%= form_for @invoice, url: external_url, authenticity_token: false do |f| %>

If you don't want to an authenticity token field be rendered at all just pass false:

<% end %>
...
<%= form_for @invoice, url: external_url, authenticity_token: 'external_token' do |f| %>

To set an authenticity token you need to pass an :authenticity_token parameter

without it, for example when you submit data to a payment gateway number and types of fields could be limited.
When you build forms to external resources sometimes you need to set an authenticity token or just render a form

=== Form to external resources

FormTagHelper#form_tag.
If you don't need to attach a form to a model instance, then check out

end
form_for(record_or_name_or_array, *(args << options.merge(builder: LabellingFormBuilder)), &block)
options = args.extract_options!
def labelled_form_for(record_or_name_or_array, *args, &block)

could do something like the following:
In many cases you will want to wrap the above in another helper, so you

of a nested fields_for call, unless it's explicitly set.
The custom FormBuilder class is automatically merged with the options

labelling_form.
variable referencing the form builder is called
The rendered template is people/_labelling_form and the local

<%= render f %>

In this case, if you use this:

<% end %>
<%= f.submit %>
<%= f.check_box :admin %>
<%= f.text_area :biography %>
<%= f.text_field :last_name %>
<%= f.text_field :first_name %>
<%= form_for @person, url: { action: "create" }, builder: LabellingFormBuilder do |f| %>

automatically add labels to form inputs.
custom builder. For example, let's say you made a helper to
FormBuilder and override or define some more helpers, then use your
You can also build forms using a customized FormBuilder class. Subclass

=== Customized form builders

<% end %>
<% end %>
...
<%= f.fields_for(:comments, include_id: false) do |cf| %>
<%= form_for(@post) do |f| %>

Example:

thus there is no primary key for comments.
In the following example the Post model has many Comments stored within it in a NoSQL database,

to disable the hidden id.
Some ORM systems do not use IDs on nested models so in this case you want to be able
This is used to maintain the correlation between the form data and its associated model.
The form_for method automatically includes the model id as a hidden field in the form.

=== Removing hidden model id's


...



The HTML generated for this would be:

<% end %>
...
<%= form_for(@post, data: { behavior: "autosave" }, html: { name: "go" }) do |f| %>

the HTML key. Example:
You can set data attributes directly by passing in a data hash, but all other HTML options must be wrapped in

=== Setting HTML options


...



The HTML generated for this would be:

<% end %>
...
<%= form_for(@post, remote: true) do |f| %>

Example:

side (all elements available in params).
behavior. The form submission will work just like a regular submission as viewed by the receiving
in the options hash creates a form that will allow the unobtrusive JavaScript drivers to modify its

remote: true

Specifying:

=== Unobtrusive JavaScript

called _method will carry the intended verb for the server to interpret.
supported by HTML forms, the form will be set to POST and a hidden input
in the options hash. If the verb is not GET or POST, which are natively

method: (:get|:post|:patch|:put|:delete)

You can force the form to use the full array of HTTP verbs by setting

=== Setting the method

@comment = Comment.new.
Where @document = Document.find(params[:id]) and

<% end %>
...
<%= form_for([@document, @comment]) do |f| %>

to the document given that the routes are set correctly:
If your resource has associations defined, for example, you want to add comments

<% end %>
...
<%= form_for([:admin, @post]) do |f| %>

For namespaced routes, like +admin_post_url+:

<% end %>
...
<%= form_for(@post, format: :json) do |f| %>

You can also set the answer format, like this:

<% end %>
...
<%= form_for(@post, url: false) do |f| %>

You can omit the action attribute by passing url: false:

<% end %>
...
<%= form_for(@post, url: super_posts_path) do |f| %>

However you can still overwrite individual conventions, such as:

<% end %>
...
<%= form_for @post, as: :post, url: posts_path, html: { class: "new_post", id: "new_post" } do |f| %>

is equivalent to something like:

<% end %>
...
<%= form_for(Post.new) do |f| %>

And for a new record

<% end %>
...
<%= form_for @post, as: :post, url: post_path(@post), method: :patch, html: { class: "edit_post", id: "edit_post_45" } do |f| %>

is then equivalent to something like:

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

appropriate URL from the record itself. For example,
in config/routes.rb. In this case Rails will simply infer the
to a set of RESTful routes, e.g. defined using the +resources+ method
if the record passed to +form_for+ is a _resource_, i.e. it corresponds
form is going to be sent. However, further simplification is possible
need to use the :url option in order to specify where the
In the examples just shown, although not indicated explicitly, we still

=== Resource-oriented style

values of the attributes of +post+.
would produce a form with fields whose initial state reflect the current

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

representing an existing record,
variable. So, for example, if we had a _local_ variable +post+
regardless of whether the object is an instance
are taken from the attributes of the object passed to +form_for+,
Secondly, the field values shown when the form is initially displayed

would result in params[:client].

<% end %>
...
<%= form_for(@person, as: :client) do |f| %>

the :as option, e.g. -
if the object's class is +Post+. However, this can be overwritten using
hash) is actually derived from the object's _class_, e.g. params[:post]
elements within the form (hence the key that denotes them in the +params+
couple of small exceptions. First, the prefix used to name the input
This behaves in almost the same way as outlined previously, with a

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

is an existing record you wish to edit, you can create the form using
to pass a model object itself to +form_for+. For example, if @post
a string can also be used equivalently. It is also possible, however,
represented by a symbol passed to +form_for+, and we noted that
In the examples above, the object to be created or edited was

=== #form_for with a model object

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

<% end %>
<%= f.submit %>
Admin? : <%= check_box_tag "person[admin]", "1", @person.company.admin? %>
Biography : <%= text_area :person, :biography %>
Last name : <%= f.text_field :last_name %>
First name: <%= f.text_field :first_name %>
<%= form_for :person do |f| %>

from FormTagHelper. For example:
possible to use both the stand-alone FormHelper methods and methods
Also note that +form_for+ doesn't create an exclusive scope. It's still

* :html - Optional HTML attributes for the form tag.
utf8 is not output.
* :enforce_utf8 - If set to false, a hidden input with name
JavaScript drivers to control the submit behavior.
* :remote - If set to true, will allow the Unobtrusive
unnecessary unless you support browsers without JavaScript.
get the authenticity token from the meta tag, so embedding is
This is helpful when you're fragment-caching the form. Remote forms
config.action_view.embed_authenticity_token_in_remote_forms = false.
Remote forms may omit the embedded authenticity token by setting
not add authenticity_token field at all (by passing false).
Use only if you need to pass custom authenticity token string, or to
* :authenticity_token - Authenticity token to use in the form.
simulate the verb over post.
is used, a hidden input with name _method is added to
either "get" or "post". If "patch", "put", "delete", or another verb
* :method - The method to use when submitting the form, usually
with underscore on the generated HTML id.
id attributes on form elements. The namespace attribute will be prefixed
* :namespace - A namespace for your form to ensure uniqueness of
to be specified explicitly).
resource-oriented usage of +form_for+ in which the URL does not need
sent back to the current URL (We will describe below an alternative
:url option is not specified, by default the form will be
represented by a string or symbol, as in the example above, if the
So for example you may use a named route directly. When the model is
represented in the same way as values passed to +url_for+ or +link_to+.
* :url - The URL the form is to be submitted to. This may be

optional hash of options -
The rightmost argument to +form_for+ is an

@person.
existing record) will be the value of the corresponding attribute of
initially displayed (e.g. in the situation where you are editing an
@person, the default value of the field shown when the form is
if :person also happens to be the name of an instance variable
For fields generated in this way using the FormBuilder,

params[:person][:first_name].
the value entered by the user will be available in the controller as
person[first_name]. This means that when the form is submitted,
which results in an HTML tag whose +name+ attribute is

<%= text_field :person, :first_name %>

will get expanded to

<%= f.text_field :first_name %>

are used to generate fields bound to this model. Thus, for example,
:person passed to +form_for+. Methods defined on the FormBuilder
incorporates the knowledge about the model object represented by
The variable +f+ yielded to the block is a FormBuilder object that

<% end %>
<%= f.submit %>
Admin? : <%= f.check_box :admin %>

Biography : <%= f.text_area :biography %>

Last name : <%= f.text_field :last_name %>

First name: <%= f.text_field :first_name %>

<%= form_for :person do |f| %>

the object we are concerned with:
can be created by passing +form_for+ a string or symbol representing
how the form should be constructed. For a generic model object, a form
how much you wish to rely on Rails to infer automatically from the model
The method can be used in several slightly different ways, depending on

of a specific model object.
Creates a form that allows the user to create or update the attributes
def form_for(record, options = {}, &block)
  raise ArgumentError, "Missing block" unless block_given?
  case record
  when String, Symbol
    model       = nil
    object_name = record
  else
    model       = convert_to_model(record)
    object      = _object_for_form_builder(record)
    raise ArgumentError, "First argument in form cannot contain nil or be empty" unless object
    object_name = options[:as] || model_name_from_record_or_class(object).param_key
    apply_form_for_options!(object, options)
  end
  remote = options.delete(:remote)
  if remote && !embed_authenticity_token_in_remote_forms && options[:authenticity_token].blank?
    options[:authenticity_token] = false
  end
  options[:model]                               = model
  options[:scope]                               = object_name
  options[:local]                               = !remote
  options[:skip_default_ids]                    = false
  options[:allow_method_names_outside_object]   = options.fetch(:allow_method_names_outside_object, false)
  form_with(**options, &block)
end

def form_with(model: nil, scope: nil, url: nil, format: nil, **options, &block)

end
form_with(**options.merge(builder: LabellingFormBuilder), &block)
def labelled_form_with(**options, &block)

could do something like the following:
In many cases you will want to wrap the above in another helper, so you

of a nested +fields+ call, unless it's explicitly set.
The custom FormBuilder class is automatically merged with the options

labelling_form.
variable referencing the form builder is called
The rendered template is people/_labelling_form and the local

<%= render form %>

In this case, if you use:

<% end %>
<%= form.submit %>
<%= form.check_box :admin %>
<%= form.text_area :biography %>
<%= form.text_field :last_name %>
<%= form.text_field :first_name %>
<%= form_with model: @person, url: { action: "create" }, builder: LabellingFormBuilder do |form| %>

automatically add labels to form inputs.
custom builder. For example, let's say you made a helper to
FormBuilder and override or define some more helpers, then use your
You can also build forms using a customized FormBuilder class. Subclass

=== Customized form builders

<% end %>
<% end %>
...
<%= form.fields(:comments, skip_id: true) do |fields| %>
<%= form_with(model: @post) do |form| %>

thus there is no primary key for comments.
In the following example the Post model has many Comments stored within it in a NoSQL database,

to disable the hidden id.
Some ORM systems do not use IDs on nested models so in this case you want to be able
This is used to maintain the correlation between the form data and its associated model.
The +form_with+ method automatically includes the model id as a hidden field in the form.

=== Removing hidden model id's


...



generates

<% end %>
...
<%= form_with(model: @post, data: { behavior: "autosave" }, html: { name: "go" }) do |form| %>

besides id and class must be wrapped in an HTML key:
You can set data attributes directly in a data hash, but HTML options

=== Setting HTML options

called _method will carry the intended verb for the server to interpret.
supported by HTML forms, the form will be set to POST and a hidden input
in the options hash. If the verb is not GET or POST, which are natively

method: (:get|:post|:patch|:put|:delete)

You can force the form to use the full array of HTTP verbs by setting

=== Setting the method

FormOptionsHelper#collection_select and DateHelper#datetime_select.
to work with an object as a base, like
Same goes for the methods in FormOptionsHelper and DateHelper designed

<% end %>
<%= form.submit %>

<%= check_box_tag "person[admin]", "1", @person.company.admin? %>
<%= text_area :person, :biography %>

<%= form.text_field :last_name %>
<%= form.text_field :first_name %>
<%= form_with scope: :person do |form| %>

from FormTagHelper:
match the stand-alone FormHelper methods and methods
While +form_with+ uses a FormBuilder object it's possible to mix and

=== Mixing with other form helpers

Where @document = Document.find(params[:id]).

<% end %>
...
<%= form_with(model: [ @document, Comment.new ]) do |form| %>

to the document given that the routes are set correctly:
If your resource has associations defined, for example, you want to add comments

<% end %>
...
<%= form_with(model: [ :admin, @post ]) do |form| %>

For namespaced routes, like +admin_post_url+:

<%= form_with(model: @post, authenticity_token: false) %> # Disables the token.
<%= form_with(model: @post, format: :json) %>
<%= form_with(model: @post, scope: :article) %>
<%= form_with(model: @post, url: super_posts_path) %>

When not passing a block, +form_with+ just generates an opening form tag.

=== Examples

* :html - Other optional HTML attributes for the form tag.
* :data - Optional HTML data attributes.
* :class - Optional HTML class attribute.
* :id - Optional HTML id attribute.
* :builder - Override the object used to build the form.
utf8 is not output.
* :skip_enforcing_utf8 - If set to true, a hidden input with name
true (the equivalent of passing local: false).
In previous versions of Rails, that configuration option defaults to
(which has the equivalent effect of passing local: true).
As of Rails 6.1, that configuration option defaults to false
config's value is actually the inverse of what local's value would be.
from config.action_view.form_with_generates_remote_forms where the
is handled by Rails UJS as an XHR. When unspecified, the behavior is derived
When set to false, the form is submitted as a "remote form", which
When set to true, the form is submitted via standard HTTP.
* :local - Whether to use standard HTTP form submission.
unnecessary unless you support browsers without JavaScript.
get the authenticity token from the meta tag, so embedding is
This is helpful when fragment-caching the form. Remote forms
config.action_view.embed_authenticity_token_in_remote_forms = false.
Remote forms may omit the embedded authenticity token by setting
that might limit the valid fields.
Useful when submitting to an external resource like a payment gateway
skip the authenticity token field altogether.
Override with a custom authenticity token or pass false to
* :authenticity_token - Authenticity token to use in the form.
E.g. turn params[:post] into params[:article].
Pass :scope or :url to override the defaults.
existing record, however, an update form is generated.
If the model is a new record a create form is generated, if an
field's value would be "Ahoy!".
So if a +title+ attribute is set to "Ahoy!" then a +title+ input
:scope by, plus fill out input field values.
* :model - A model object to infer the :url and
with underscore on the generated HTML id.
id attributes on form elements. The namespace attribute will be prefixed
* :namespace - A namespace for your form to ensure uniqueness of
thereby how the submitted parameters are grouped in controllers.
* :scope - The scope to prefix input field names with and
Skipped if a :url is passed.
Useful when submitting to another resource type, like :json.
* :format - The format of the route the form submits to.
simulate the verb over post.
is used, a hidden input named _method is added to
either "get" or "post". If "patch", "put", "delete", or another verb
* :method - The method to use when submitting the form, usually
form just submits to the current URL.
directly. When a :scope is passed without a :url the
+url_for+ or +link_to+. For example, you may use a named route
* :url - The URL the form submits to. Akin to values passed to

==== +form_with+ options

<% end %>
...
<%= form_with scope: :post, url: posts_path do |form| %>

is equivalent to something like:

<% end %>
...
<%= form_with model: Post.new do |form| %>

And for a new record

<% end %>
...
<%= form_with scope: :post, url: post_path(@post), method: :patch do |form| %>

is then equivalent to something like:

<% end %>
...
<%= form_with model: @post do |form| %>

So when passing such a model record, Rails infers the URL and method.

defined via +resources+ in config/routes.rb.
is a _resource_. It corresponds to a set of RESTful routes, most likely
In many of the examples just shown, the +:model+ passed to +form_with+

=== Resource-oriented style

protection.
and adds an authenticity token needed for cross site request forgery
as well as the auto generated hidden fields that enable UTF-8 support
For ease of comparison the examples above left out the submit button,

respectively.
accessible as params[:title] and params[:post][:title]
their name nesting. So inputs named +title+ and post[title] are
The parameters in the forms are accessible in controllers according to





# =>
<% end %>
<%= form.text_field :but_in_forms_they_can %>
<%= form.text_field :cats_dont_have_gills %>
<%= form_with model: Cat.new do |form| %>
# Though the fields don't have to correspond to model attributes:





# =>
<% end %>
<%= form.text_field :title %>
<%= form_with model: Post.first do |form| %>
# An existing model makes an update form and fills out field values:




# =>
<% end %>
<%= form.text_field :title %>
<%= form_with model: Post.new do |form| %>
# Using a model infers both the URL and scope:




# =>
<% end %>
<%= form.text_field :title %>
<%= form_with scope: :post, url: posts_path do |form| %>
# Adding a scope prefixes the input field names:




# =>
<% end %>
<%= form.text_field :title %>
<%= form_with url: false do |form| %>
# With an intentionally empty URL:




# =>
<% end %>
<%= form.text_field :title %>
<%= form_with url: posts_path do |form| %>
# Using just a URL:

Creates a form tag based on mixing URLs, scopes, or models.
def form_with(model: nil, scope: nil, url: nil, format: nil, **options, &block)
  options = { allow_method_names_outside_object: true, skip_default_ids: !form_with_generates_ids }.merge!(options)
  if model
    if url != false
      url ||= polymorphic_path(model, format: format)
    end
    model   = _object_for_form_builder(model)
    scope ||= model_name_from_record_or_class(model).param_key
  end
  if block_given?
    builder = instantiate_builder(scope, model, options)
    output  = capture(builder, &block)
    options[:multipart] ||= builder.multipart?
    html_options = html_options_for_form_with(url, model, **options)
    form_tag_with_body(html_options, output)
  else
    html_options = html_options_for_form_with(url, model, **options)
    form_tag_html(html_options)
  end
end

def hidden_field(object_name, method, options = {})

# =>
hidden_field(:user, :token)

# =>
hidden_field(:post, :tag_list)

# =>
hidden_field(:signup, :pass_confirm)
==== 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(object_name, method, options = {})
  Tags::HiddenField.new(object_name, method, self, options).render
end

def html_options_for_form_with(url_for_options = nil, model = nil, html: {}, local: !form_with_generates_remote_forms,

def html_options_for_form_with(url_for_options = nil, model = nil, html: {}, local: !form_with_generates_remote_forms,
  skip_enforcing_utf8: nil, **options)
  html_options = options.slice(:id, :class, :multipart, :method, :data, :authenticity_token).merge!(html)
  html_options[:remote] = html.delete(:remote) || !local
  html_options[:method] ||= :patch if model.respond_to?(:persisted?) && model.persisted?
  if skip_enforcing_utf8.nil?
    if options.key?(:enforce_utf8)
      html_options[:enforce_utf8] = options[:enforce_utf8]
    end
  else
    html_options[:enforce_utf8] = !skip_enforcing_utf8
  end
  html_options_for_form(url_for_options.nil? ? {} : url_for_options, html_options)
end

def instantiate_builder(record_name, record_object, options)

def instantiate_builder(record_name, record_object, options)
  case record_name
  when String, Symbol
    object = record_object
    object_name = record_name
  else
    object = record_name
    object_name = model_name_from_record_or_class(object).param_key if object
  end
  builder = options[:builder] || default_form_builder_class
  builder.new(object_name, object, self, options)
end

def label(object_name, method, content_or_options = nil, options = nil, &block)

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

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

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

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

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

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

# =>
label(:post, :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(:post, :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(:post, :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(object_name, method, content_or_options = nil, options = nil, &block)
  Tags::Label.new(object_name, method, self, content_or_options, options).render(&block)
end

def month_field(object_name, method, options = {})


# =>
month_field("user", "born_on")
@user.born_on = Date.new(1984, 1, 27)

of DateTime and ActiveSupport::TimeWithZone.
on the object's value, which makes it behave as expected for instances
The default value is generated by trying to call +strftime+ with "%Y-%m"

# =>
month_field("user", "born_on")

Returns a text_field of type "month".
def month_field(object_name, method, options = {})
  Tags::MonthField.new(object_name, method, self, options).render
end

def number_field(object_name, method, options = {})

Supports the same options as FormTagHelper#number_field_tag.

==== Options

Returns an input tag of type "number".
def number_field(object_name, method, options = {})
  Tags::NumberField.new(object_name, method, self, options).render
end

def password_field(object_name, method, options = {})

# =>
password_field(:account, :pin, size: 20, class: 'form_input')

# =>
password_field(:user, :password, onchange: "if ($('#user_password').val().length > 30) { alert('Your password needs to be shorter!'); }")

# =>
password_field(:account, :secret, class: "form_input", value: @account.secret)

# =>
password_field(:login, :pass, size: 20)
==== Examples

shown. For security reasons this field is blank by default; pass in a value via +options+ if this is not desired.
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 an input tag of the "password" type tailored for accessing a specified attribute (identified by +method+) on an object
def password_field(object_name, method, options = {})
  Tags::PasswordField.new(object_name, method, self, options).render
end

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

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

#
# =>
radio_button("post", "category", "java")
radio_button("post", "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(object_name, method, tag_value, options = {})
  Tags::RadioButton.new(object_name, method, self, tag_value, options).render
end

def range_field(object_name, method, options = {})

Supports the same options as FormTagHelper#range_field_tag.

==== Options

Returns an input tag of type "range".
def range_field(object_name, method, options = {})
  Tags::RangeField.new(object_name, method, self, options).render
end

def search_field(object_name, method, options = {})

# =>
search_field(:user, :name, autosave: true, onsearch: true)
# =>
search_field(:user, :name, autosave: false, onsearch: true)
# =>
search_field(:user, :name, onsearch: true)
# =>
search_field(:user, :name, autosave: true)
# Assume request.host returns "www.example.com"
# =>
search_field(:user, :name, results: 3)
# =>
search_field(:user, :name, autosave: false)
# =>
search_field(:user, :name)

some browsers.
assigned to the template (identified by +object_name+). Inputs of type "search" may be styled differently by
Returns an input of type "search" for accessing a specified attribute (identified by +method+) on an object
def search_field(object_name, method, options = {})
  Tags::SearchField.new(object_name, method, self, options).render
end

def telephone_field(object_name, method, options = {})


# =>
telephone_field("user", "phone")

Returns a text_field of type "tel".
def telephone_field(object_name, method, options = {})
  Tags::TelField.new(object_name, method, self, options).render
end

def text_area(object_name, method, options = {})

#
# #{@entry.body}
# =>
# #{@application.notes}
# =>
# #{@comment.text}
# =>
# #{@post.body}
# =>