**DO NOT READ THIS FILE ON GITHUB, GUIDES ARE PUBLISHED ON https://guides.rubyonrails.org.** Action View Form Helpers ======================== Forms in web applications are an essential interface for user input. However, form markup can quickly become tedious to write and maintain because of the need to handle form control naming and its numerous attributes. Rails does away with this complexity by providing view helpers for generating form markup. However, since these helpers have different use cases, developers need to know the differences between the helper methods before putting them to use. After reading this guide, you will know: * How to create search forms and similar kind of generic forms not representing any specific model in your application. * How to make model-centric forms for creating and editing specific database records. * How to generate select boxes from multiple types of data. * What date and time helpers Rails provides. * What makes a file upload form different. * How to post forms to external resources and specify setting an `authenticity_token`. * How to build complex forms. -------------------------------------------------------------------------------- NOTE: This guide is not intended to be a complete documentation of available form helpers and their arguments. Please visit [the Rails API documentation](https://api.rubyonrails.org/) for a complete reference. Dealing with Basic Forms ------------------------ The main form helper is `form_with`. ```erb <%= form_with do |form| %> Form contents <% end %> ``` When called without arguments like this, it creates a form tag which, when submitted, will POST to the current page. For instance, assuming the current page is a home page, the generated HTML will look like this: ```html
Form contents
``` You'll notice that the HTML contains an `input` element with type `hidden`. This `input` is important, because non-GET forms cannot be successfully submitted without it. The hidden input element with the name `authenticity_token` is a security feature of Rails called **cross-site request forgery protection**, and form helpers generate it for every non-GET form (provided that this security feature is enabled). You can read more about this in the [Securing Rails Applications](security.html#cross-site-request-forgery-csrf) guide. ### A Generic Search Form One of the most basic forms you see on the web is a search form. This form contains: * a form element with "GET" method, * a label for the input, * a text input element, and * a submit element. To create this form you will use `form_with` and the form builder object it yields. Like so: ```erb <%= form_with url: "/search", method: :get do |form| %> <%= form.label :query, "Search for:" %> <%= form.text_field :query %> <%= form.submit "Search" %> <% end %> ``` This will generate the following HTML: ```html
``` TIP: Passing `url: my_specified_path` to `form_with` tells the form where to make the request. However, as explained below, you can also pass ActiveRecord objects to the form. TIP: For every form input, an ID attribute is generated from its name (`"q"` in above example). These IDs can be very useful for CSS styling or manipulation of form controls with JavaScript. IMPORTANT: Use "GET" as the method for search forms. This allows users to bookmark a specific search and get back to it. More generally Rails encourages you to use the right HTTP verb for an action. ### Helpers for Generating Form Elements The form builder object yielded by `form_with` provides numerous helper methods for generating form elements such as text fields, checkboxes, and radio buttons. The first parameter to these methods is always the name of the input. When the form is submitted, the name will be passed along with the form data, and will make its way to the `params` in the controller with the value entered by the user for that field. For example, if the form contains `<%= form.text_field :query %>`, then you would be able to get the value of this field in the controller with `params[:query]`. When naming inputs, Rails uses certain conventions that make it possible to submit parameters with non-scalar values such as arrays or hashes, which will also be accessible in `params`. You can read more about them in chapter [Understanding Parameter Naming Conventions](#understanding-parameter-naming-conventions) of this guide. For details on the precise usage of these helpers, please refer to the [API documentation](https://api.rubyonrails.org/classes/ActionView/Helpers/FormTagHelper.html). #### Checkboxes Checkboxes are form controls that give the user a set of options they can enable or disable: ```erb <%= form.check_box :pet_dog %> <%= form.label :pet_dog, "I own a dog" %> <%= form.check_box :pet_cat %> <%= form.label :pet_cat, "I own a cat" %> ``` This generates the following: ```html ``` The first parameter to `check_box` is the name of the input. The second parameter is the value of the input. This value will be included in the form data (and be present in `params`) when the checkbox is checked. #### Radio Buttons Radio buttons, while similar to checkboxes, are controls that specify a set of options in which they are mutually exclusive (i.e., the user can only pick one): ```erb <%= form.radio_button :age, "child" %> <%= form.label :age_child, "I am younger than 21" %> <%= form.radio_button :age, "adult" %> <%= form.label :age_adult, "I am over 21" %> ``` Output: ```html ``` As with `check_box`, the second parameter to `radio_button` is the value of the input. Because these two radio buttons share the same name (`age`), the user will only be able to select one of them, and `params[:age]` will contain either `"child"` or `"adult"`. NOTE: Always use labels for checkbox and radio buttons. They associate text with a specific option and, by expanding the clickable region, make it easier for users to click the inputs. ### Other Helpers of Interest Other form controls worth mentioning are hidden fields, password fields, number fields, date and time fields, and many more: ```erb <%= form.hidden_field :parent_id, value: "foo" %> <%= form.password_field :password %> <%= form.number_field :price, in: 1.0..20.0, step: 0.5 %> <%= form.range_field :discount, in: 1..100 %> <%= form.date_field :born_on %> <%= form.time_field :started_at %> <%= form.datetime_local_field :graduation_day %> <%= form.month_field :birthday_month %> <%= form.week_field :birthday_week %> <%= form.search_field :name %> <%= form.email_field :address %> <%= form.telephone_field :phone %> <%= form.url_field :homepage %> <%= form.color_field :favorite_color %> ``` Output: ```html ``` Hidden inputs are not shown to the user but instead hold data like any textual input. Values inside them can be changed with JavaScript. IMPORTANT: The search, telephone, date, time, color, datetime, datetime-local, month, week, URL, email, number, and range inputs are HTML5 controls. If you require your app to have a consistent experience in older browsers, you will need an HTML5 polyfill (provided by CSS and/or JavaScript). There is definitely [no shortage of solutions for this](https://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-Browser-Polyfills), although a popular tool at the moment is [Modernizr](https://modernizr.com/), which provides a simple way to add functionality based on the presence of detected HTML5 features. TIP: If you're using password input fields (for any purpose), you might want to configure your application to prevent those parameters from being logged. You can learn about this in the [Securing Rails Applications](security.html#logging) guide. Dealing with Model Objects -------------------------- ### Binding a Form to an Object The `:model` argument of `form_with` allows us to bind the form builder object to a model object. This means that the form will be scoped to that model object, and the form's fields will be populated with values from that model object. For example, if we have an `@article` model object like: ```ruby @article = Article.find(42) puts @article.title # => My Title puts @article.body # => My Body ``` The following form: ```erb <%= form_with model: @article do |form| %> <%= form.text_field :title %> <%= form.text_area :body, size: "60x10" %> <%= form.submit %> <% end %> ``` Outputs: ```html
``` The are several things to notice here: * The form `action` is automatically filled with an appropriate value for `@article`. * The form fields are automatically filled with the corresponding values from `@article`. * The form field names are scoped with `article[...]`. This means that `params[:article]` will be a hash containing all these field's values. You can read more about the significance of input names in chapter [Understanding Parameter Naming Conventions](#understanding-parameter-naming-conventions) of this guide. * The submit button is automatically given an appropriate text value. TIP: Conventionally your inputs will mirror model attributes. However, they don't have to! If there is other information you need you can include it in your form just as with attributes and access it via `params[:article][:my_nifty_non_attribute_input]`. #### The `fields_for` Helper You can create a similar binding without actually creating `
` tags with the `fields_for` helper. This is useful for editing additional model objects with the same form. For example, if you had a `Person` model with an associated `ContactDetail` model, you could create a form for creating both like so: ```erb <%= form_with model: @person do |person_form| %> <%= person_form.text_field :name %> <%= fields_for :contact_detail, @person.contact_detail do |contact_detail_form| %> <%= contact_detail_form.text_field :phone_number %> <% end %> <% end %> ``` which produces the following output: ```html
``` The object yielded by `fields_for` is a form builder like the one yielded by `form_with`. ### Relying on Record Identification The Article model is directly available to users of the application, so - following the best practices for developing with Rails - you should declare it **a resource**: ```ruby resources :articles ``` TIP: Declaring a resource has a number of side effects. See [Rails Routing from the Outside In](routing.html#resource-routing-the-rails-default) guide for more information on setting up and using resources. When dealing with RESTful resources, calls to `form_with` can get significantly easier if you rely on **record identification**. In short, you can just pass the model instance and have Rails figure out model name and the rest: ```ruby ## Creating a new article # long-style: form_with(model: @article, url: articles_path) # short-style: form_with(model: @article) ## Editing an existing article # long-style: form_with(model: @article, url: article_path(@article), method: "patch") # short-style: form_with(model: @article) ``` Notice how the short-style `form_with` invocation is conveniently the same, regardless of the record being new or existing. Record identification is smart enough to figure out if the record is new by asking `record.persisted?`. It also selects the correct path to submit to, and the name based on the class of the object. WARNING: When you're using STI (single-table inheritance) with your models, you can't rely on record identification on a subclass if only their parent class is declared a resource. You will have to specify `:url`, and `:scope` (the model name) explicitly. #### Dealing with Namespaces If you have created namespaced routes, `form_with` has a nifty shorthand for that too. If your application has an admin namespace then ```ruby form_with model: [:admin, @article] ``` will create a form that submits to the `ArticlesController` inside the admin namespace (submitting to `admin_article_path(@article)` in the case of an update). If you have several levels of namespacing then the syntax is similar: ```ruby form_with model: [:admin, :management, @article] ``` For more information on Rails' routing system and the associated conventions, please see [Rails Routing from the Outside In](routing.html) guide. ### How do forms with PATCH, PUT, or DELETE methods work? The Rails framework encourages RESTful design of your applications, which means you'll be making a lot of "PATCH", "PUT", and "DELETE" requests (besides "GET" and "POST"). However, most browsers _don't support_ methods other than "GET" and "POST" when it comes to submitting forms. Rails works around this issue by emulating other methods over POST with a hidden input named `"_method"`, which is set to reflect the desired method: ```ruby form_with(url: search_path, method: "patch") ``` Output: ```html
...
``` When parsing POSTed data, Rails will take into account the special `_method` parameter and act as if the HTTP method was the one specified inside it ("PATCH" in this example). IMPORTANT: All forms using `form_with` implement `remote: true` by default. These forms will submit data using an XHR (Ajax) request. To disable this include `local: true`. To dive deeper see [Working with JavaScript in Rails](working_with_javascript_in_rails.html#remote-elements) guide. Making Select Boxes with Ease ----------------------------- Select boxes in HTML require a significant amount of markup - one `