Creating Controllers and Actions
The router has picked BooksController#index. Now Ruby code must run: fetch the books, choose what to send back. That code is a controller action, and every action ends in one of two ways.
The rule
Every action ends in a render or a redirect.
A controller is a class that inherits from ApplicationController. Its public methods are actions; private methods are helpers the router cannot reach.
bin/rails generate controller Books index showclass BooksController < ApplicationController
def index
@books = Book.order(:title)
end # renders app/views/books/index.html.erb
def show
@book = Book.find(params[:id])
end
def create
@book = Book.new(book_params)
if @book.save
redirect_to @book, notice: "Book added."
else
render :new, status: :unprocessable_entity
end
end
endRender builds a response body now, from a template. If you do nothing, Rails renders the template named after the action, in the folder named after the controller: index → books/index.html.erb. This is implicit rendering. render :new picks another template in the same request, keeping all your instance variables.
Redirect sends a 302 with a new URL; the browser then makes a second request. redirect_to @book is shorthand for redirect_to book_path(@book). Instance variables do not survive a redirect, because it is a new request.
Other endings: render json: @book for APIs, and head :no_content for a response with no body.
The shortcut
After any action that changes data, ask "did it work?" Worked → redirect (so a refresh cannot repeat the POST). Failed → render the form again with an error status (so the typed values and errors stay).
The form posts
POST /bookswith an empty title reachescreate.
The trap is calling both, or calling one twice, in the same action. Rails raises DoubleRenderError. Use return or an if/else so each path ends exactly once.
Drills
Answer fast — trust the rule.
The index action of BooksController sets @books and calls nothing else. What happens?
After a successful update, why redirect instead of rendering show?
Which statement about redirect_to is true?
A method in a controller is listed under private. What does that mean?
Remember
- Every action ends in a render or a redirect — exactly once.
- Shortcut: changed data and it worked, redirect; it failed, render the form with an error status.
- Trap: DoubleRenderError from rendering and redirecting in the same path.
