RoR Forms and Form Helpers
Forms let users send data to your Rails application. Every signup page, login form, search box, and settings panel is a form. Rails provides form helpers — Ruby methods that generate the correct HTML form elements and wire them to your models automatically.
The form_with Helper
form_with is the main Rails form builder. Pass it a model object and it generates a form that points to the correct URL and uses the correct HTTP method.
<%= form_with model: @article do |f| %> <%= f.label :title %> <%= f.text_field :title %> <%= f.label :body %> <%= f.text_area :body %> <%= f.submit "Save Article" %> <% end %>
Rails generates different HTML depending on whether @article is a new record or an existing one:
New record (@article.new_record? = true):
<form action="/articles" method="post">
Existing record (@article.persisted? = true):
<form action="/articles/3" method="post">
<input type="hidden" name="_method" value="patch">
You write the same form code for both new and edit pages. Rails handles the difference automatically.
Form Input Types
Text inputs: <%= f.text_field :name %> ← single line text <%= f.text_area :body %> ← multi-line text <%= f.password_field :password %> ← masked input <%= f.email_field :email %> ← email with validation hint <%= f.number_field :age %> ← numeric keyboard on mobile <%= f.url_field :website %> ← URL with validation hint <%= f.search_field :query %> ← search input Selection inputs: <%= f.check_box :published %> ← true/false checkbox <%= f.radio_button :status, "active" %> ← one of many <%= f.select :category, ["books", "tech", "food"] %> ← dropdown <%= f.collection_select :user_id, User.all, :id, :name %> ← dropdown from DB Date and time: <%= f.date_field :birthday %> <%= f.datetime_local_field :scheduled_at %> <%= f.time_field :meeting_time %> File: <%= f.file_field :avatar %>
Labels
Always pair each input with a label. Labels improve accessibility and let users click the label text to focus the input.
<%= f.label :email, "Your Email Address" %> <%= f.email_field :email %> Generates: <label for="user_email">Your Email Address</label> <input type="email" name="user[email]" id="user_email">
A Complete Registration Form
app/views/users/new.html.erb
<h1>Create Your Account</h1>
<% if @user.errors.any? %>
<ul>
<% @user.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
<% end %>
<%= form_with model: @user do |f| %>
<p>
<%= f.label :name, "Full Name" %>
<%= f.text_field :name, placeholder: "Jane Doe" %>
</p>
<p>
<%= f.label :email %>
<%= f.email_field :email, placeholder: "you@example.com" %>
</p>
<p>
<%= f.label :password %>
<%= f.password_field :password %>
</p>
<p>
<%= f.label :password_confirmation, "Confirm Password" %>
<%= f.password_field :password_confirmation %>
</p>
<%= f.submit "Create Account" %>
<% end %>
How Form Data Reaches the Controller
Form field name: user[email]
|
v
Controller params: params[:user][:email]
|
v
Strong parameters: params.require(:user).permit(:name, :email, :password)
|
v
Model: User.new(user_params)
Select Dropdowns
Simple array options:
<%= f.select :country, ["USA", "Canada", "UK", "India"] %>
Array with labels and values:
<%= f.select :role, [["Admin", "admin"], ["Editor", "editor"], ["Viewer", "viewer"]] %>
Include a blank option:
<%= f.select :category, ["Books", "Tech"], include_blank: "-- Choose a Category --" %>
Populate from database:
<%= f.collection_select :author_id, Author.all, :id, :name,
{ include_blank: "Select Author" } %>
Checkboxes and Radio Buttons
Single checkbox (boolean field): <%= f.check_box :newsletter_opt_in %> <%= f.label :newsletter_opt_in, "Send me the newsletter" %> Multiple checkboxes (store as array): <% ["Ruby", "Python", "JavaScript"].each do |lang| %> <%= check_box_tag "user[languages][]", lang %> <%= label_tag lang %> <% end %> Radio buttons: <%= f.radio_button :plan, "free" %> <%= f.label :plan_free, "Free" %> <%= f.radio_button :plan, "pro" %> <%= f.label :plan_pro, "Pro" %>
Forms Without a Model
Use form_with url: when you need a form that does not map to a model — like a search form:
<%= form_with url: search_path, method: :get do |f| %> <%= f.label :q, "Search" %> <%= f.search_field :q, placeholder: "Type to search..." %> <%= f.submit "Search" %> <% end %>
The search term arrives in params[:q]. Use method: :get so the search query appears in the URL, which lets users share and bookmark search results.
Form Submission Flow
User fills in form and clicks Submit
|
v
Browser sends HTTP POST to /users
with body: user[name]=Alice&user[email]=alice@x.com
|
v
Router: POST /users → UsersController#create
|
v
Controller reads params, calls User.new(user_params)
|
v
Validations run
|
+-- Pass → record saved → redirect to profile page
+-- Fail → render :new → form reappears with errors shown
Rails form helpers reduce the amount of HTML you write, handle CSRF tokens automatically, and keep your forms synchronized with your models.
