Interested in learning Ruby on Rails? This tutorial covers topics such as how to create a genre controller and genre view, as well as how to enhance the aesthetics of the genre view. Mastering these concepts can provide a strong foundation for a career in web development.
Key Insights
- The tutorial starts by demonstrating how to create a genre controller, which involves generating a controller for genres and defining the 'show' method in the genres controller.
- Creating a genre view involves creating a new document in your code editor, saving it in the genre views folder, and adding code to display the name of the genre as the page heading.
- To enhance the look of the genre page, the tutorial suggests using the same code from the index page and creating a partial that can be used on both the index and genre pages.
- The tutorial also includes steps for handling potential errors, such as a NoMethodError that may occur when there is no mention of @movies in the genres controller.
- To resolve this conflict, the tutorial recommends creating a local variable in the movie_list file and explicitly passing the list of movies to that local variable.
- Finally, the tutorial advises testing the changes in a browser to ensure that the genre page is working properly and looks more appealing.
Dive into our step-by-step Ruby on Rails tutorial that covers creating and improving a genre view and controller, guiding you through the culmination of previous exercises and enabling you to understand how MVC works together.
This exercise is excerpted from Noble Desktop’s past web development training materials. Noble Desktop now teaches JavaScript and the MERN Stack in our Full Stack Development Certificate. To learn current skills in web development, check out our coding bootcamps in NYC and live online.
Topics Covered in This Ruby on Rails Tutorial:
Creating a Genre Controller, Creating a Genre View, Improving the Look of the Genre View
Exercise Preview
Photos courtesy of istockphoto, © Sergey Kashkin, Image #318828, Sveta Demidoff, Image #2712135, Korhan Karacan, Image #15095805
Exercise Overview
In the previous exercise, we added a genre for the movies. Let’s work on making each genre clickable, so it leads to a page with other movies from that genre. This is a good opportunity to explore how MVC works together, considering that we now have a total of three models that interact with one another.
-
If you completed the previous exercises, you can skip the following sidebar. We recommend you finish the previous exercises before starting this one. If you haven’t finished them, do the following sidebar.
If You Did Not Do the Previous Exercises (3A–5B)
- Close any files you may have open.
- Open the Finder and navigate to Class Files > yourname-Rails Class
- Open Terminal.
- Type
cd
and a single space (do NOT press Return yet). - Drag the yourname-Rails Class folder from the Finder to the Terminal window and press ENTER.
- Run
rm -rf flix
to delete your copy of the Flix site. - Run
Git clone https://bitbucket.org/Noble Desktop/flix.Git
to copy the Flix Git repository. - Type
cd flix
to enter the new directory. - Type
Git checkout 5B
to bring the site up to the end of the previous exercise. - Run
bundle
to install any necessary gems. - Run
yarn install—check-files
to install JavaScript dependencies.
Getting Started
Open the Finder and navigate to Class Files > yourname-Rails Class
Open Terminal.
Type
cd
and a single space (do NOT press Return yet).Drag the flix folder from the Finder to the Terminal window.
Make sure you’re in Terminal and hit Return to change into the new folder.
Creating a Genre Controller
The first step will be creating a controller for genres.
Switch to the Terminal.
-
Type the following:
rails generate controller genres
Remember, controller names are always plural. Terminal should print the names of a few files it has just created.
-
In your code editor, open flix > config > routes.rb
We suggest opening the flix folder in your code editor if it allows you to (like Sublime Text does).
-
Make
genres
a resource (providing it with resourceful routes) by typing the following around line 6:resources :movies resources :genres, only: :show
This line of code means that we’ll have resourceful routes for genre pages, but only for the
show
page. (We can add other CRUD down the line if needed.) Save the file.
Open flix > app > controllers > genres_controller.rb
-
Define the
show
method by typing:class GenresController < ApplicationController def show @genre = Genre.find(params[:id]) end end
Hopefully this formulation is starting to look more familiar by now. Now let’s create a view!
Save the file.
Creating a Genre View
Create a new blank document in your code editor.
-
When we ran
rails generate controller genres
, Rails created a genre views folder for us (how thoughtful!), so we should save the file there. Do a File > Save As and save the blank document as follows:- Name it: show.html.erb
- Save it into: yourname-Rails Class > flix > app > views > genres
NOTE: You now have two files named show.html.erb in the Flix application folder. They must have that name so they work properly with the strict organizational system of Rails—you’ll just have to be careful about editing the right one (the one in views > genres and the one in views > movies). Luckily, one has much more information in it than the other, so it shouldn’t be too hard to keep them straight.
-
Type the following on the first line:
<h1><%= @genre.name %></h1>
This will print the name of the genre as the page heading.
-
Add the following bold code:
<h1><%= @genre.name %></h1> <% @genre.movies.each do |movie| %> <p><%= link_to movie.title, movie %><p> <% end %>
These lines of code will go through all the movies and display links to all the movies in the selected genre. This is some basic output so we can test if the feature is working before we do anything fancier.
Save the file.
Close the file.
-
Open to app > views > movies > show.html.erb in your code editor.
Let’s make each genre into a clickable link that will lead to the genre page.
-
Find the following area of code, around line 16:
<div> <span>Genre:</span> <%= @movie.genre.name unless @movie.genre.nil? %> </div>
-
Add the following bold code:
<div> <span>Genre:</span> <%= link_to(@movie.genre.name, @movie.genre) unless @movie.genre.nil? %> </div>
Save the file.
-
In Terminal type the following to start the server:
rails server
In a browser go to localhost:,000
Click on Text M for Murder.
-
In the Movie Details sidebar notice that the genre (Horror) is now clickable! Click on it to see the genre page listing two movies as plain text links.
NOTE: The address of the page should be something like localhost:,000/genres/1
Improving the Look of the Genre View
What we’ve done so far with genres satisfies the basic requirements, but we should really improve the look of the genres page. It’s a little sad-looking—clickable movie posters and mini-descriptions (like we have on the main movies page) would really improve it.
In fact, let’s use the exact code from the index page. Rather than having the same code in two places which would not be DRY, we ought to make a partial that can be used on the index and genre pages.
In your code editor open app > views > movies > index.html.erb
-
Select the following code, which should be lines 14–30 (but double-check that it starts and ends with
ul
tags):<ul class="content-links-list clearfix"> <% @movies.each do |movie| %> <li> <%= link_to movie_path(movie) do %> <div class="clearfix"> <%= image_tag("posters/thumbs/#{movie.poster_image}", class: 'imgLeft') %> <div class="clearfix"> <h3><%= movie.title %></h3> <div><%= movie.cast %></div> <div><%= movie.mpaa_rating %>, <%= movie.runtime %> minutes</div> <div><span class="button">More ›</span></div> </div> </div> <% end %> </li> <% end %> </ul>
Cut the selected code (Cmd–X).
So you’ll know which line to render the partial, hit Return once to create a blank line. We’ll do that in a few steps.
Create a new blank file.
Paste the code into the blank file.
Save the new file as
_
movie_
list.html.erb (make sure it has an initial underscore, indicating it’s a partial!) into the app > views > movies folder (where it should be by default).Switch back to index.html.erb
-
In the blank line you created a moment ago, type the following:
<div class="clearfix"> <%= render 'movie_list' %> <div class="inset-block">
Remember, we don’t put the initial underscore of partials in the call to render them; Rails already knows that it’s rendering a partial.
Save the file.
-
In a browser go to localhost:,000 and make sure we have not broken the index page. It should still be looking good, phew!
Let’s render the partial on the genres page.
Open app > views > genres > show.html.erb in your code editor. (Remember, there are two files named show.html.erb in different folders, so be careful about which one is currently being edited.)
-
Right now the entire document should consist of these four lines of code:
<h1><%= @genre.name %></h1> <% @genre.movies.each do |movie| %> <p><%= link_to movie.title, movie %><p> <% end %>
-
Replace the final three lines of code with the bold code as follows:
<h1><%= @genre.name %></h1> <%= render 'movies/movie_list' %>
Because we’re in the genres controller, not the movies controller, it’s good form to specify rendering
movies/movie_list
(instead of simplymovie_list
). Again, there is no initial underscore in this path because Rails is still smart enough to understand that it’s rendering a partial. Save the file.
-
Switch to the browser, navigate to one of the genres pages such as localhost:,000/genres/1 and you will receive an error, a
NoMethodError
this time.Here’s a bit of a snag. On the movies index page we have an instance variable called
@movies
which is automatically shared with the partial. That instance variable is defined in the movies controller in the index method with the line of code@movies = Movie.all
. Then, in the_
movie_
list partial, we refer to@movies.each
. In fact, it is the exact line in the partial where we mention@movies.each
that is causing the error; Rails has helpfully highlighted the line in red.In the genres controller we have the instance variable
@genre
but there is no mention of@movies
, thus the partial throws an error. (Why did the page work before? Because before when we were rendering the partial, we were referencing@genre.movies.each
, which is not the same variable as@movies
!)How do we resolve this conflict? We could write something like
@movies = @genre.movies
before rendering the partial, but that’s not best practice. Instead, we could create a local variable in the_
movie_
list file and explicitly pass the list of movies to that local variable. Because we’re likely to use this partial on different parts of the site in the future, this seems like a more reusable, flexible approach. Switch to
_
movie_
list.html.erb in your code editor.-
The first two lines of the document should look like this:
<ul class="content-links-list clearfix"> <% @movies.each do |movie| %>
-
Remove the @ sign before
movies.each
so the code reads as follows:<ul class="content-links-list clearfix"> <% movies.each do |movie| %>
Save the file.
Switch to index.html.erb in your code editor.
-
Find the line of code that renders the partial, around line 14:
<%= render 'movie_list' %>
-
Add the following bold code:
<%= render 'movie_list', movies: @movies %>
This means we are explicitly passing the
@movies
instance variable intomovies
. We are telling Rails to expect a movie object to be passed here. Save the file.
Switch to app > views > genres > show.html.erb in your code editor.
-
Add the following bold code to the line that renders the partial:
<%= render 'movies/movie_list', movies: @genre.movies %>
Save the file.
Switch to the browser, navigate to localhost:,000/movies and notice that it should still be working properly.
Click on any movie and then click its genre. The genre page should be working perfectly and looking much more attractive with the movie posters and mini-descriptions. Great!
Back in Terminal hit CTRL–C to shut down the server.