Pebellslearn by building
0%
RoadmapsMatrixCoursesSandboxSign in
Action View  ›  Capstone Project

Forms with form_with

form_with 18 minform_with model: builds a form whose URL and HTTP method come from the record, field helpers name inputs so strong parameters can read them, and the record's errors are shown when a save fails.

Forms with form_with

Forms are where members hand data to Bookclub, and they have to agree with three other parts of the app: the route (which URL and method), the controller (which params), and the model (which errors). form_with builds forms that agree with all three automatically.

The rule

Give form_with the model; it picks the URL, the method and the names.

<%# app/views/books/_form.html.erb %>
<%= form_with model: book do |f| %>
  <% if book.errors.any? %>
    <div class="errors">
      <h2><%= pluralize(book.errors.count, "error") %> stopped this book being saved:</h2>
      <ul>
        <% book.errors.full_messages.each do |message| %>
          <li><%= message %></li>
        <% end %>
      </ul>
    </div>
  <% end %>

  <%= f.label :title %>
  <%= f.text_field :title %>

  <%= f.label :pages %>
  <%= f.number_field :pages %>

  <%= f.label :genre %>
  <%= f.select :genre, ["Fantasy", "History", "Science"] %>

  <%= f.check_box :available %>
  <%= f.label :available %>

  <%= f.submit %>
<% end %>

What form_with model: book decides for you:

Book is… Form goes to Method Button says
new (not saved) /books POST → create "Create Book"
saved (id 7) /books/7 PATCH → update "Update Book"

Browsers only send GET and POST, so for PATCH Rails adds a hidden _method field. It also adds a hidden authenticity token that proves the form came from your site (CSRF protection).

Field helpers name inputs book[title], book[pages] and so on, so everything arrives under params[:book] — exactly what book_params permits. Each helper also fills in the current value, so the edit form shows the saved data.

For nested resources pass both records: form_with model: [@book, @review] posts to /books/7/reviews. Without a model, give a URL: form_with url: search_path, method: :get.

You will meet form_for in older code. It did the same job and is replaced by form_with.

The shortcut

Trace the loop: form → params → model → errors → form. If the save fails, the controller renders the form with the same object, so the typed values and the error list come back together.

A book with no titleStep 1 of 4
  1. Submit

    The new form posts book[title]="" and book[pages]=412 to /books.

The trap is redirecting after a failed save. The new request has a fresh, empty book, so the errors and the typed values are lost.

Drills

Answer fast — trust the rule.

quick drill

form_with model: Book.new submits to which URL and method?

quick drill

What name does f.text_field :title give its input inside form_with model: @book?

quick drill

Why does a Rails form include a hidden authenticity token?

quick drill

Which call builds a review form for @book that posts to /books/7/reviews?

quick drill

A save fails and the controller calls redirect_to new_book_path. What does the member see?

Remember

  • Give form_with the model; it picks the URL, the method and the names.
  • Shortcut: form → params → model → errors → form, via render on failure.
  • Trap: redirecting after a failed save loses the errors.

Practice — level up

0/1 solved

Write your answer, then compare it with a rubric and a model answer.

ExplainOne form for new and edit

Explain how one _form partial using form_with model: book both creates and updates books. Say what URL and method it uses in each case, how the field names match strong parameters, and how the form shows a missing-title error after a failed save.