Rails Guide — Part 3 Controller Actions Continued

James JingChao Yu
5 min readAug 23, 2021

--

Continuing from last week’s blog on Rails controller, today we will take a look at what else we can accomplish inside of a controller, getting data from the routes via the params hash, the importance of the application controller, and what exactly is the concerns folder inside of the controllers directory.

In our previous project, we have a home, contact page, and a complete routes for books. Taking a look at our routes.rb file, here’s what we have:

Suppose we want our books objects to show up on our home page. How would we achieve this? We have a pages controller and a books controller, the books controller has an index action that grabs all books with the query @books = Book.all, but our pages controller has no such action.

Any controller has access to any models inside of Rails. To replicate the index action in the books controller, we can simply do this:

Next, we can print out the books in the home.html.erb file inside of the views/pages:

As you can see, this is the same to what we did with the books index page.

Before we talk about the params hash. Let’s go ahead and build out the show.html.erb page for books. Remember last time we’d already implemented the show action inside of the controller:

This might look like it’s an empty method, but on line 2, the before_action with the private method set_book is called for the show method.

Here’s a quick implementation of the show.html.erb file:

And if we go to a particular book page with the URL localhost:3000/books/1

When we used the resources :books method inside of our routes.rb, one of the routes that got generated was get ‘books/:id’, to: ‘books#show’, as: ‘book’

We can prove it inside of the Terminal with rails routes:

When we navigate localhost:3000/books/1, this 1 is a dynamic value (also a column name inside of the books table that Postgresql automatically created for us) that we are telling Rails to store it inside of the params hash, with the key id pointing to it.

Essentially, this is what we have: params = {id: 1}

We have named the variable id because it’s a column that exists in our table. But we could have named it anything we want. To demonstrate, let’s change it to isbn. First let’s make the change inside of the routes:

On line 6 we are telling Rails to give us all the resources routes except show. And on line 7, we define our own show path and we are passing in isbn as the variable.

A quick check with rails routes | grep book, we can see the route is successfully created:

Now in our books controller, we no longer have a id variable, instead we have an isbn. All we have to do is change find to find_by:

We can also do an alternative syntax with find_by_isbn and pass in the params[:isbn] argument. Whenever we create a table column, Rails will generate a helper method named find_by_column_name for us.

Restarting the Rails server, and going to localhost:3000/books/, if you type in an isbn (found in our seeds.rb file), we can see the result:

The last topic we will discuss today is controller concerns. Suppose later on we were asked to add toys and video games to our site, both databases would contain an audience column (children, teen, adult) just like we have with books. And we want our users to be able to see all items with a target audience with a link or a button click. We could have a controller action where we query the each model and get all of the items with a specific audience. But a smarter way would be to have a separate helper method, and that’s where controller concerns come in.

Controller concerns are modules where you put some functionalities that might not belong to any specific controller, or are shared among a few controllers, so you would not need to repeat your code. Let’s build out the items by audience feature in our app.

Inside of our app/controllers/concerns, create a new item_by_audience.rb file. Inside of it, let’s create a module named ItemByAudience:

Our module will extend the ActiveSupport::Concern module, at this time, it will only have 1 method called adult, which will return all book objects with the audience of adult. In our case, it will be three books. Imagine we have a few other models: toys, video games, inside of the adult method is where we can grab all of them, and make them available in the view files.

In our application controller, we simply have to include our newly created module:

Back to our home.html.erb file, we have access to the instance variable @adult_books:

Refreshing our homepage, we can see everything is working perfectly:

Next week we will move onto the Model component within our Rails app! See you then!

--

--

No responses yet