A Rails Controller for Books

New Series on Rails Controllers

This is the first post in a new series that explores the Rails controllers in detail. This post covers the basics, providing a brief overview of controllers, why we need a controller, and how to create one. We'll start exploring more advanced stuff about controllers starting from the next post.

6 min read

A few months ago I published the Rails Router handbook, which was received quite well (even getting a boost from DHH). Ever since, I've wanted to take another topic and do a similar deep-dive. And after the router, the obvious next step for an incoming request is the controller, and that's what I'll explore in the upcoming posts.

Note: If you're a seasoned Rails developer, much of this post may seem very basic. However, I want to create a comprehensive resource for Rails programmers, and every guide has to start somewhere. Sometimes revisiting the basics can often reveal new insights, even if you've been working on it for a long time. So I hope you'll bear with me. Also, in the upcoming posts in the series, we'll cover other advanced topics, so stay tuned.

With that, let's begin with the basics of controllers.

Introduction to Rails Controllers

Here is a Rails controller:

# app/controllers/products_controller.rb

class ProductsController < ApplicationController
  def index
    @products = Product.all
  end

  def show
    @product = Product.find(params[:id])
  end
end

As you can see, a Rails controller is a Ruby class that represents a particular resource in your application, in this case a product. But it can be anything, such as a user, an account, or an article. By convention, the controller class name is appended with the word "Controller", and they're always placed under the app/controllers directory.

The methods in the controller (also called actions) represent an individual endpoint of an HTTP request. In the above example, our controller represents the products, with actions to display all products as well as a single product.

By convention, the URL endpoint /products is mapped (by the router) to the ProductsController#index action and the products/1 endpoint is mapped to the ProductsController#show action, with the parameter 1 being available in the params[:id]. (We' learn about the parameters in a future post).

Also notice that your controller typically inherits from the ApplicationController, stored in the application_controller.rb file. This class itself derives from the ActionController::Base class, which provides the controller functionality.

# app/controllers/application_controller.rb

class ApplicationController < ActionController::Base
end

You can directly inherit from the base controller, but extending it from the ApplicationController allows you to centralize and share logic common to all controllers in your application.

Hope that gave you a basic idea of what a Rails controller looks like. Now let's go one step deeper and learn the need for the controllers.

Why Do We Need Controllers?

Controllers organize and group all the request-handling logic for a single resource into a single class.

HTTP is a request-response based protocol. The incoming request hits your server, which forwards it to your Rails application, which processes the request, generates the response, and sends it back to the browser.

As we've seen in the routing handbook, the Rails Router receives the request and forwards it to the code that processes the request to build the response. The entrypoint to this code lives in a Controller.

Controllers are the heart of your Rails application. They are the C in the MVC pattern, which stands for Model-View-Controller. In MVC, the controller serves as an intermediary between the model and the view. It's main role is to control the flow of data and user interactions within the application.

A controller is mainly responsible for:

  1. Receiving the incoming request
  2. Authenticate the user
  3. Co-ordinating with the model to manage the application logic
  4. Selecting and rendering a view

Whenever users visit your application, they're essentially calling an action in your controllers. After the Rails router parses the incoming URL, it directs the flow to the controller. In a way, controllers act as coordinators for your application, directing how various parts of your application (models, views, etc.) interact with each other.

💡
When a user visits your Rails application, they're basically telling your app to execute a method (called an action) on a controller class.

For example, the logic to handle product-related HTTP requests live inside the ProductsController class. This class includes methods to show, create, update, and delete projects.

Let's Create a Controller

To quickly generate a new controller, you can run rails generate controller command, passing the name of the resource. For example, to create a controller class for handling post-related logic, you'll run the following command:

rails generate controller posts

It will create a new controller class named PostsController in a app/controllers/posts_controller.rb file. Along with it, the command also generates a bunch of other files, but we can ignore them for now.

Let's open this generated controller file and examine its contents:

class PostsController < ApplicationController
end

As you can see, it's empty. To handle incoming requests, we need to write an action method in it. Let's add a method to show a particular post. We'll name this method show.

class PostsController < ApplicationController
  def show
  end
end

This method is empty. To show something on the screen, we'll need two things.

  1. A route that will direct the incoming request to this show method.
  2. A view that will be shown to the user.

Let's add the route first.

Rails.application.routes.draw do
  resources :posts, only: [ :show ]
end

Next, let's create a view file named show.html.erb under the app/views directory. By convention, Rails will render the view file named after the action, in this case action.

<h1>First Post</h1>

<p>This is the first post.</p>

That's it. Restart your Rails app and go to localhost:3000/posts/1. This URL matches the route we've created and Rails will execute the show action, rendering the show view, and you'll be greeted with the first post.

Congratulations, you've just created your first Rails controller.

Access Controller Instance Variables in View

The magic of Rails is that you can create instance variables in the controller's action method and access these variables in the view. This lets you make your views dynamic. For example, let's pull the title and body of the post via instance variables.

First, we'll create the necessary instance variables.

class PostsController < ApplicationController
  def show
    @title = "First Post"
    @body = "This is the first post."
  end
end

Next, we'll access these instance variables in the view.

<h1>
  <%= @title %>
</h1>

<p>
  <%= @body %>
</p>

If you reload the page, it should still display the title and the body of the post. However, a big difference is that since the title and body are being set in a Ruby class, you have much more flexibility to use any logic you want to create them, for example, pulling them from a database or even an external service. Being in a Ruby class also allows you to keep your code more maintainable.

Let's stop here, we'll cover parameters in the next post. In the future posts in the series, we'll learn more about controller, such as how they work with user-submitted data, how the coordinate models and how they can render the views. In fact, here's a preview of the upcoming posts in the series.

Rails Controller Handbook Index
Rails Controller Handbook Index

When finished, the handbook will be published on books.writesoftwarewell.com. Stay tuned!


That's a wrap. I hope you found this article helpful and you learned something new.

As always, if you have any questions or feedback, didn't understand something, or found a mistake, please leave a comment below or send me an email. I reply to all emails I get from developers, and I look forward to hearing from you.

If you'd like to receive future articles directly in your email, please subscribe to my blog. Your email is respected, never shared, rented, sold or spammed. If you're already a subscriber, thank you.

👉
Building web applications with Rails and Hotwire is something I really enjoy. If you're looking for some help with your Ruby on Rails application — whether you're starting a new project or maintaining a legacy codebase — I can help.

Check out my one-person software studio: https://typeangle.com/ and reach out if you think I'm a good fit for your needs.