Controllers & Actions

Reviewed & published by Brayan K

In Ruby on Rails the controller is the coordinator: each public method, called an action, receives a request, works with models, and decides what to send back. It's the C in MVC.

Part of the free Ruby course at LearnCodingFast — hands-on lessons with worked examples and the output they print, plus practice exercises and a quick quiz.

By the end of this lesson you'll write the standard CRUD actions, read the params hash, choose between render and redirect_to, and share setup with before_action.

What You'll Learn in This Lesson

1️⃣ Actions, params, render and redirect

Each action is a method on the controller. It reads input from params, talks to a model, and then either renders a view or redirect_tos another URL.

# app/controllers/posts_controller.rb
class PostsController < ApplicationController
  # GET /posts  -> list all posts
  def index
    @posts = Post.all
  end

  # GET /posts/:id  -> show one post
  def show
    @post = Post.find(params[:id])   # params[:id] comes from the URL
  end

  # GET /posts/new  -> render a blank form
  def new
    @post = Post.new
  end

  # POST /posts  -> save the submitted form
  def create
    @post = Post.new(post_params)
    if @post.save
      redirect_to @post              # success: go to the new post
    else
      render :new                    # failure: re-show the form
    end
  end
end

The remaining actions complete CRUD. Notice the private post_params method — strong parameters whitelist the fields you accept.

# The remaining CRUD actions: edit, update, destroy.
class PostsController < ApplicationController
  # GET /posts/:id/edit  -> form pre-filled with the record
  def edit
    @post = Post.find(params[:id])
  end

  # PATCH /posts/:id  -> save changes
  def update
    @post = Post.find(params[:id])
    if @post.update(post_params)
      redirect_to @post
    else
      render :edit
    end
  end

  # DELETE /posts/:id  -> delete the record
  def destroy
    @post = Post.find(params[:id])
    @post.destroy
    redirect_to posts_path           # back to the list
  end

  private

  # Strong parameters: only allow these fields.
  def post_params
    params.require(:post).permit(:title, :body)
  end
end

2️⃣ Sharing Setup with before_action

Several actions need the same record. A before_action runs a method before chosen actions, so you load @post once instead of repeating the lookup.

# before_action runs shared setup before chosen actions.
class PostsController < ApplicationController
  # Run set_post before show, edit, update, and destroy.
  before_action :set_post, only: [:show, :edit, :update, :destroy]

  def show; end          # @post is already loaded
  def edit; end          # @post is already loaded

  private

  def set_post
    @post = Post.find(params[:id])   # no more repeating this line!
  end
end

Your turn. Complete the index and show actions for articles.

# 🎯 YOUR TURN — complete the index and show actions.
class ArticlesController < ApplicationController
  # 1) List every article.
  def index
    @articles = Article.____        # 👉 TODO: fetch them all
  end

  # 2) Show one article by its id from the URL.
  def show
    @article = Article.find(params[:____])   # 👉 TODO: the id key
  end
end

# ✅ Expected:
#    Article.all
#    params[:id]

Mini-Challenge: Match Action to Request

For each HTTP request, name the controller action that handles it.

# 🎯 MINI-CHALLENGE: name the right action.
# For each request, write the controller action that runs.
#
# 1. POST /posts                     -> ______
# 2. GET  /posts/9/edit              -> ______
# 3. PATCH /posts/9                  -> ______
# 4. DELETE /posts/9                 -> ______
#
# ✅ Example answers:
#    create
#    edit
#    update
#    destroy

# your answers here

Common Errors (and the fix)

Pro Tips

📋 Quick Reference — Controllers

ConceptSyntax
List alldef index; @posts = Post.all; end
Find onePost.find(params[:id])
Show a viewrender :new
Go elsewhereredirect_to @post
Strong paramsparams.require(:post).permit(:title)
Shared setupbefore_action :set_post

🎉 Lesson Complete!

Practice quiz

Which controller action conventionally LISTS all records?

  • show
  • index
  • create
  • edit

Answer: index. The index action lists all records of a resource.

How does a controller read submitted form and URL data?

  • Through the params hash
  • Through the @request variable
  • Through cookies only
  • Through the routes file

Answer: Through the params hash. Incoming data (query string, form fields, path segments) is available in the params hash.

After a successful create, what should the controller usually do?

  • render :new again
  • redirect_to the new record (or its index)
  • raise an error
  • call params.save

Answer: redirect_to the new record (or its index). On success you typically redirect_to the record, following the POST-redirect-GET pattern.

What is the purpose of before_action?

  • It deletes the database
  • It runs shared setup code before chosen actions
  • It defines the routes
  • It renders the layout

Answer: It runs shared setup code before chosen actions. before_action runs a method before specified actions, ideal for shared setup like loading a record.

Which action handles the DELETE request to remove a record?

  • remove
  • delete
  • destroy
  • drop

Answer: destroy. The destroy action handles deletion of a record.

What does render :new do inside an action?

  • Redirects the browser to /new
  • Renders the new view template without a new request
  • Creates a database record
  • Defines a route

Answer: Renders the new view template without a new request. render :new displays the new template directly, keeping the current request (and any errors).

The difference between render and redirect_to is:

  • They are identical
  • render runs a migration; redirect_to deletes data
  • render shows a view in the same request; redirect_to tells the browser to make a new request
  • redirect_to is only for JSON

Answer: render shows a view in the same request; redirect_to tells the browser to make a new request. render produces a response now; redirect_to sends the browser to a new URL, triggering a fresh request.

In show, how do you find the record from the URL /posts/5?

  • Post.all
  • Post.new
  • Post.find(params[:id])
  • Post.delete(5)

Answer: Post.find(params[:id]). Post.find(params[:id]) looks up the record whose id matches the :id from the path.

Which pair of actions render forms rather than change data?

  • new and edit
  • create and update
  • index and destroy
  • show and create

Answer: new and edit. new and edit render forms; create and update are the actions those forms submit to.

Why use strong parameters like params.require(:post).permit(:title)?

  • To speed up the server
  • To allow only approved fields, preventing mass-assignment of unexpected data
  • To define routes
  • To render a partial

Answer: To allow only approved fields, preventing mass-assignment of unexpected data. Strong parameters whitelist permitted fields, protecting against unwanted mass assignment.

Continue this course

Frequently asked questions

What are the seven standard controller actions?

They mirror the seven RESTful routes: index lists all records, show displays one, new renders a blank form, create saves the submitted form, edit renders a form pre-filled with an existing record, update saves changes to it, and destroy deletes it. new and edit just render forms; create, update, and destroy actually change data. Following these names keeps your controller aligned with resources :posts in the routes file, so everything wires up automatically. Most CRUD controllers you write will have exactly these actions.

What is the params hash?

params is a hash-like object holding all the data that came in with the request: values from the URL path (like the :id in /posts/5, available as params[:id]), query string parameters, and submitted form fields (often nested, like params[:post][:title]). Your actions read params to know which record to load or what data to save. Because params can contain anything a user sends, you protect writes with strong parameters — params.require(:post).permit(:title, :body) — which only lets approved fields through.

What's the difference between render and redirect_to?

render produces a response within the current request: render :new shows the new template right now, which is why you use it when a save fails — the user keeps their input and sees the validation errors. redirect_to instead tells the browser to make a brand-new request to another URL, for example redirect_to @post after a successful create. The rule of thumb: render after a failure (so the form and errors persist) and redirect after a success (following the POST-redirect-GET pattern, which avoids duplicate submissions on refresh).

When should I use before_action?

Use before_action to run shared setup code before several actions, keeping your controller DRY. The classic case is loading a record: before_action :set_post, only: [:show, :edit, :update, :destroy] runs a set_post method that assigns @post = Post.find(params[:id]) once, instead of repeating that line in four actions. before_action is also used for things like requiring a logged-in user or authorizing access. You can scope it with only: or except: to control exactly which actions it runs before.