Skip to main content
April 1, 2026Noble Desktop Publishing Team/9 min read

Model Relationships: Creating a Genre View

Master Rails MVC Architecture Through Genre Views

Core MVC Components in This Tutorial

Model Relationships

Working with three interconnected models: movies, genres, and their associations. Understanding how data flows between related entities.

Controller Logic

Creating resourceful routes and controller methods. Learning the show action pattern and parameter handling in Rails.

View Optimization

Building reusable partials and improving user interface. Creating clickable elements and attractive layouts.

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

preview genre view

Photos courtesy of istockphoto, © Sergey Kashkin, Image #318828, Sveta Demidoff, Image #2712135, Korhan Karacan, Image #15095805

Exercise Overview

In the previous exercise, we established genre functionality for our movies. Now we'll take the next logical step: making each genre clickable to create a dedicated page showcasing all movies within that category. This enhancement provides an excellent opportunity to explore Rails' Model-View-Controller (MVC) architecture in action, particularly how three interconnected models collaborate to deliver seamless user experiences.

This exercise demonstrates fundamental principles of modern web development: creating intuitive navigation patterns, maintaining DRY (Don't Repeat Yourself) code through partials, and building scalable controller architectures. These concepts remain essential in today's Rails applications, from small-scale projects to enterprise-level systems.

  1. If you completed the previous exercises, you can skip the following sidebar. We strongly recommend completing the previous exercises before proceeding, as they establish the foundational models and relationships this exercise builds upon. If you haven't finished them, follow the setup instructions below.

    MVC Pattern in Action

    This exercise demonstrates how three models interact within the MVC framework. You'll see firsthand how controllers coordinate between models and views to create dynamic, interconnected pages.

If You Did Not Do the Previous Exercises (3A–5B)

  1. Close any files you may have open.
  2. Open the Finder and navigate to Class Files > yourname-Rails Class
  3. Open Terminal.
  4. Type cd and a single space (do NOT press Return yet).
  5. Drag the yourname-Rails Class folder from the Finder to the Terminal window and press ENTER.
  6. Run rm -rf flix to delete your existing copy of the Flix site.
  7. Run git clone https://bitbucket.org/Noble Desktop/flix.git to copy the Flix Git repository.
  8. Type cd flix to enter the new directory.
  9. Type git checkout 5B to bring the site up to the end of the previous exercise.
  10. Run bundle to install any necessary gems.
  11. Run yarn install --check-files to install JavaScript dependencies.

Getting Started

Let's begin by setting up our development environment and ensuring we're working with the correct project files.

  1. Open the Finder and navigate to Class Files > yourname-Rails Class

  2. Open Terminal.

  3. Type cd and a single space (do NOT press Return yet).

  4. Drag the flix folder from the Finder to the Terminal window.

  5. Make sure you're in Terminal and hit Return to change into the project folder.

Environment Setup Process

1

Navigate to Project Directory

Use Finder to locate your Rails class folder and open Terminal for command line operations.

2

Change Directory

Use the cd command with drag-and-drop functionality to navigate into your flix project folder.

3

Verify Project State

Ensure your Rails application is ready for the genre controller and view implementation.

Creating a Genre Controller

Our first step involves generating a dedicated controller to handle genre-related requests. Following Rails conventions, this controller will manage the presentation layer for genre data, separating concerns cleanly from our existing movie functionality.

  1. Switch to the Terminal.

  2. Generate the controller by typing the following:

    rails generate controller genres

    Remember, controller names follow Rails' pluralization conventions. Terminal will display the names of several files it has created, including the controller, helper, and test files.

  3. In your code editor, open flix > config > routes.rb

    We recommend opening the entire flix folder in your code editor for easier navigation between files.

  4. Configure the genre routes by adding the following around line 6:

    resources :movies
    resources :genres, only: :show

    This configuration provides resourceful routes for genres, but restricts them to the show action only. This approach follows the principle of least exposure—we're only creating the routes we actually need. Additional CRUD operations can be added later as requirements evolve.

  5. Save the file.

  6. Open flix > app > controllers > genres_controller.rb

  7. Implement the show method by adding:

    class GenresController < ApplicationController
       def show
          @genre = Genre.find(params[:id])
       end
    end

    This pattern should be familiar by now—we're following Rails' convention of finding a record by its ID and making it available to the view through an instance variable. This approach maintains consistency with RESTful design principles.

  8. Save the file.

Now that our controller foundation is in place, let's move on to creating the corresponding view to present genre data to users.

Controller Naming Convention

Remember that controller names are always plural in Rails. This follows the RESTful convention where controllers manage collections of resources.

Generated Files and Routes

Controller Generation

Rails creates the genres_controller.rb file automatically along with associated view folders and basic structure.

Resourceful Routes

Using 'only: :show' restricts routes to just the show action, providing clean URL structure without unnecessary endpoints.

Creating a Genre View

With our controller logic established, we need to create the view template that will render genre information and associated movies for our users.

  1. Create a new blank document in your code editor.

  2. The Rails generator has already created a genre views folder for us. Save this blank document with File > Save As using these specifications:

    • Name: show.html.erb
    • Location: yourname-Rails Class > flix > app > views > genres

    NOTE: You'll now have two files named show.html.erb in your Rails application—one for movies and one for genres. This naming convention is required by Rails' organizational system. The files serve different controllers, so their content will help distinguish them during development.

  3. Create the page heading by typing:

    <h1><%= @genre.name %></h1>

    This displays the genre name as the primary heading, establishing clear context for users.

  4. Add basic movie listing functionality with the following code:

    <h1><%= @genre.name %></h1>
    <% @genre.movies.each do |movie| %>
    <p><%= link_to movie.title, movie %></p>
    <% end %>

    This code leverages the association between genres and movies, iterating through all movies in the selected genre and creating clickable links to each. We're starting with basic output to verify functionality before implementing more sophisticated styling.

  5. Save the file.

  6. Close the file.

  7. Open app > views > movies > show.html.erb in your code editor.

    Now we'll make the genre labels clickable, creating seamless navigation between movies and their associated genres.

  8. Locate the genre display code around line 16:

    <div>
       <span>Genre:</span>
       <%= @movie.genre.name unless @movie.genre.nil? %>
    </div>
  9. Transform the genre name into a clickable link:

    <div>
       <span>Genre:</span>
       <%= link_to(@movie.genre.name, @movie.genre) unless @movie.genre.nil? %>
    </div>
  10. Save the file.

  11. Start the Rails development server:

    rails server
  12. In your browser, navigate to localhost:3000

  13. Click on Text M for Murder to view a movie detail page.

  14. In the Movie Details sidebar, notice that the genre (Horror) is now clickable. Click on it to access the genre page, which displays movies as basic text links.

    NOTE: The URL should follow the pattern localhost:3000/genres/1, demonstrating proper RESTful routing.

Our basic genre functionality is now operational, but the presentation needs significant enhancement to match professional standards. Let's improve the visual design and user experience.

File Organization Important

You now have two show.html.erb files in different folders. Rails' strict organizational system requires this naming, so be careful to edit the correct file in the genres views folder.

View Creation Process

1

Create View File

Save as show.html.erb in the app/views/genres directory that Rails automatically created during controller generation.

2

Add Genre Heading

Use ERB syntax to display the genre name as the main page heading with proper HTML structure.

3

Loop Through Movies

Iterate through all movies in the genre using the association, creating clickable links for each movie title.

4

Make Genres Clickable

Update the movie show view to turn genre names into clickable links using Rails link_to helper method.

Improving the Look of the Genre View

While our current implementation satisfies basic functional requirements, the plain-text presentation falls short of modern user expectations. Instead of recreating the attractive movie display code we already have, we'll implement Rails partials—a powerful feature for maintaining DRY principles while ensuring consistent presentation across different sections of our application.

Partials are reusable view components that promote code maintainability and consistency. By extracting common presentation logic into partials, we can modify the display format in one place and have those changes propagate throughout the application.

  1. Open app > views > movies > index.html.erb in your code editor.

  2. Select the movie listing code (lines 14–30, verify it's enclosed in 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>
  3. Cut the selected code (Cmd–X on Mac, Ctrl–X on Windows).

  4. Press Return once to create a blank line where we'll render our partial.

  5. Create a new blank document for our partial.

  6. Paste the movie listing code into this new document.

  7. Save this file as _movie_list.html.erb in the app > views > movies folder.

    The initial underscore is Rails' convention for identifying partial templates. This naming convention allows Rails to automatically recognize and handle these reusable components.

  8. Return to index.html.erb and add the partial rendering call:

    <div class="clearfix">
       <%= render 'movie_list' %>
       <div class="inset-block">

    Notice we omit the underscore when referencing partials—Rails automatically handles this convention.

  9. Save the file.

  10. Test the changes by visiting localhost:3000 in your browser. The movies index page should display exactly as before, confirming our refactoring was successful.

  11. Open app > views > genres > show.html.erb (ensure you're editing the genres version, not the movies version).

  12. The file should currently contain:

    <h1><%= @genre.name %></h1>
    <% @genre.movies.each do |movie| %>
    <p><%= link_to movie.title, movie %></p>
    <% end %>
  13. Replace the basic movie listing with our enhanced partial:

    <h1><%= @genre.name %></h1>
    <%= render 'movies/movie_list' %>

    Since we're in the genres controller, we specify the full path movies/movie_list to reference the partial from the movies views directory.

  14. Save the file.

  15. Navigate to a genre page (e.g., localhost:3000/genres/1) and you'll encounter a NoMethodError.

    This error occurs because our partial references @movies, an instance variable that exists in the movies controller but not in the genres controller. The genres controller only defines @genre. This is a common challenge when sharing partials across different controllers—we need to make our partial more flexible and reusable.

    Rather than creating duplicate instance variables, we'll implement local variables within the partial. This approach provides better encapsulation and makes our code more maintainable.

  16. Open _movie_list.html.erb in your code editor.

  17. Find the loop declaration at the beginning:

    <ul class="content-links-list clearfix">
       <% @movies.each do |movie| %>
  18. Remove the @ symbol to convert it to a local variable:

    <ul class="content-links-list clearfix">
       <% movies.each do |movie| %>
  19. Save the file.

  20. Return to index.html.erb and modify the render call to pass the movies data:

    <%= render 'movie_list', movies: @movies %>

    This explicitly passes the @movies instance variable to the partial's local movies variable.

  21. Save the file.

  22. In app > views > genres > show.html.erb, update the render call:

    <%= render 'movies/movie_list', movies: @genre.movies %>

    Here we pass the genre's associated movies to the same local variable, making our partial truly reusable across different contexts.

  23. Save the file.

  24. Test both pages: navigate to localhost:3000/movies to verify the index still works properly.

  25. Click on any movie, then click its genre link. The genre page should now display beautifully formatted movie cards with posters, cast information, and ratings—matching the professional appearance of the main movies page.

  26. In Terminal, press Ctrl–C to shut down the development server.

Congratulations! You've successfully implemented a sophisticated genre browsing system that demonstrates several crucial Rails concepts: RESTful routing, controller organization, view partials, and clean separation of concerns. This foundation provides excellent scalability for future enhancements like filtering, sorting, or advanced search functionality.

DRY Principle in Action

Rather than duplicating code between index and genre pages, we're creating a reusable partial. This follows the Don't Repeat Yourself principle, making code more maintainable.

Partial Implementation Benefits

Pros
Eliminates code duplication between pages
Creates consistent styling across the application
Makes maintenance easier with single source of truth
Enables flexible reuse with local variables
Cons
Requires careful variable management
Initial setup takes more time than copying code
Debugging can be slightly more complex

Partial Creation and Implementation

1

Extract Existing Code

Cut the movie list HTML from index.html.erb, specifically lines 14-30 that contain the ul tags and movie iteration.

2

Create Partial File

Save the extracted code as _movie_list.html.erb with the required underscore prefix to indicate it's a partial.

3

Update Variable References

Change @movies to movies in the partial to use local variables instead of instance variables for better reusability.

4

Render with Parameters

Update both index and genre views to render the partial while passing the appropriate movie collections as local variables.

Cross-Controller Partial Rendering

When rendering partials from different controllers, use the full path like 'movies/movie_list'. Rails automatically handles the underscore prefix for partial files.

Key Takeaways

1Rails follows strict MVC patterns where controllers coordinate between models and views, demonstrated through the genre controller managing movie-genre relationships
2Resourceful routes with restrictions (only: :show) provide clean URL structures while limiting unnecessary endpoints for focused functionality
3Controller naming conventions require plural forms, and Rails automatically generates associated view folders and basic file structure
4View partials eliminate code duplication and follow DRY principles, making applications more maintainable and consistent
5Local variables in partials provide better reusability than instance variables, allowing the same partial to work across different controllers
6Model associations enable powerful data relationships, where @genre.movies automatically provides all movies belonging to a specific genre
7Rails' organizational system requires specific file naming and folder structures, with multiple files having the same name in different directories
8The link_to helper method creates dynamic, clickable elements that integrate seamlessly with Rails routing system

RELATED ARTICLES