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

MVC: Creating a Model, View, & Controller

Master Ruby on Rails MVC Architecture Fundamentals

From Theory to Practice

This tutorial moves beyond Ruby theory into practical Rails application development, building a real movie management system similar to Fandango or Rotten Tomatoes.

Topics Covered in This Ruby on Rails Tutorial:

MVC: Model-view-controller, Creating a New Rails Site for Flix, Generating a New Model, Editing a Migration File, Populating a Database with a Seed File, Creating a New Controller

Exercise Preview

mvc creating mvc exercise preview

Exercise Overview

It's time to move beyond Ruby fundamentals and dive into Rails development. In this hands-on exercise, you'll begin building Flix, a sophisticated movie information and review management system inspired by platforms like IMDb and Rotten Tomatoes. This project will serve as your practical introduction to Rails' foundational architecture pattern: Model-View-Controller (MVC).

MVC: Model-View-Controller

Before we start coding, it's crucial to understand that Rails applications are not simple websites—they are robust, scalable web applications designed for complex data management and user interactions. Modern Rails applications power everything from e-commerce platforms to API services, delivering not just HTML but JSON, XML, and real-time data streams to diverse client applications.

Rails is built on the MVC (Model-View-Controller) architectural pattern, a time-tested approach used across programming languages and frameworks. This pattern promotes clean code organization, maintainability, and scalability by separating application logic into three distinct, interconnected components:

  • Model objects handle data persistence and business logic. In our previous recipe application, the recipe model provided methods like @recipe.title and @recipe.prep_time to access and manipulate recipe data. In the Flix application, our models will manage movies, cast members, user reviews, and ratings. Rails implements this layer through ActiveRecord, an Object-Relational Mapping (ORM) system that translates database records into Ruby objects and provides powerful query interfaces.

  • Views are responsible for presentation logic and user interface rendering. Each application component typically has multiple views—index pages for listings, show pages for individual records, and forms for data entry. Views are template files that combine HTML with embedded Ruby code to dynamically display data. They also capture user input through forms and interface elements. Rails handles this layer through ActionView, which provides templating engines, helper methods, and form builders.

  • Controllers orchestrate the interaction between models and views, serving as the application's traffic directors. When a user navigates to a URL like /movies/1, the Rails router dispatches the request to the appropriate controller action. The controller then retrieves necessary data from models, processes business logic, and selects the appropriate view for rendering the response. Controllers also handle form submissions, user authentication, and API responses. Rails implements this through ActionController, which provides request handling, parameter processing, and response generation capabilities.

The MVC pattern enforces strict separation of concerns—each component has clearly defined responsibilities and should never overstep its boundaries. For instance, models should never generate HTML markup, and views should never directly query databases. This separation becomes crucial as applications grow in complexity. Remember our recipe directions formatting challenge? Rather than embedding <br> tags directly in the database content (violating MVC principles), we used the simple_format helper method in the view template (/app/views/recipes/show.html.erb). This approach maintained data integrity while providing flexible presentation options—essential when your data needs to appear in multiple formats across web pages, mobile apps, or API responses.

MVC Architecture Components

Model (ActiveRecord)

Stores and manages data. Provides methods to access and edit information like recipe.title and recipe.prep_time. Handles movies, cast members, and comments.

View (ActionView)

Displays information to users through templates. Formats data for presentation and receives user input. Each major component has its own view series.

Controller (ActionController)

Bridges models and views. Routes requests, contacts models for data, and passes information to views. Manages user interfaces and form submissions.

MVC Separation Principle

Components should be distinct with clear responsibilities. Models never render HTML, views never contain business logic, and controllers only coordinate between them.

Creating a New Rails Site for Flix

Let's establish the foundation for our Flix application by generating a new Rails project. The Rails generator creates a complete application structure with sensible defaults, saving hours of manual configuration.

  1. Open Terminal.

  2. Type cd and then press the spacebar once but do not hit Return yet!

  3. Switch to the Finder.

  4. Navigate into Class Files.

  5. Drag the yourname-Rails Class folder from the Finder to the Terminal window (this will enter the path in Terminal).

  6. Switch to the Terminal.

  7. Press Return to change to that directory.

  8. In Terminal type:

    rails new flix

    This command creates a complete Rails application structure with all necessary dependencies, configuration files, and directory hierarchies. The process may take a few minutes as Rails installs gems, configures webpack for asset management, and establishes the database structure. Modern Rails applications come pre-configured with essential tools like Turbo for enhanced user interactions and Import Maps for JavaScript module management.

  9. Go into the directory by typing:

    cd flix
  10. Type the following to examine the complete application structure created by Rails:

    ls

    You'll see directories for models (app/models), views (app/views), controllers (app/controllers), configuration (config), database management (db), and much more. This standardized structure is one of Rails' greatest strengths—any Rails developer can immediately navigate and understand your project layout.

Rails Project Setup Process

1

Navigate to Project Directory

Open Terminal, type cd with space, drag your Rails Class folder from Finder to Terminal, then press Return

2

Generate New Rails Application

Run 'rails new flix' command to create all basic Rails app components automatically

3

Enter Project Directory

Change into the new directory with 'cd flix' and explore created files using 'ls' command

Creating a New Controller

Now we'll create the first component of our MVC architecture: a controller to handle movie-related requests. Controllers act as the entry point for user interactions, coordinating between your data models and presentation views.

  1. In Terminal, generate a new controller with the following command:

    rails generate controller movies

    Rails generators follow strict naming conventions that enable powerful automation. The controller name should be plural (movies) because it will handle multiple movie records, while model names are typically singular.

  2. Terminal will display a comprehensive list of generated files. Each file marked with the bright green create indicator serves a specific purpose in the Rails ecosystem:

    Controller Generation Command

    The 'rails generate controller movies' command creates the essential controller structure and associated directories for handling user requests in your Rails application.

Rails Generate Controller Files Explained

  • app/controllers/movies_controller.rb is the controller class where you'll define action methods to handle different types of requests (displaying lists, showing individual movies, handling form submissions, etc.).
  • app/views/movies is the dedicated directory for movie-related view templates. Unlike the rails generate scaffold command, generate controller creates only the directory structure—you'll craft the actual view templates to match your specific requirements.
  • test/controllers/movies_controller_test.rb provides a foundation for automated testing. Modern Rails development emphasizes test-driven development (TDD) to ensure application reliability and facilitate refactoring.
  • app/helpers/movies_helper.rb is a module for view-specific utility methods. Helper methods keep complex logic out of view templates while providing reusable functionality like date formatting, link generation, or data transformation.
  • The generated SCSS asset files provide a starting point for component-specific styling, supporting Rails' asset pipeline for optimized CSS delivery.
  • These generated files provide structure without content—it's your responsibility to implement the specific functionality. While you could manually create these files and directories, the Rails generator ensures perfect naming conventions and file placement. Rails follows "Convention over Configuration" principles, meaning file names and locations must be precisely correct for automatic loading and routing to work. Even experienced developers use generators to avoid typos and maintain consistency across large applications.

  • Let's start the Rails development server to examine our current application state:

    rails server

    The Rails server provides live reloading and detailed error reporting, essential tools for efficient development workflows.

  • In a browser window, navigate to localhost:3000 or reload if you're already there. The Rails welcome page appears, confirming your application is running correctly.

  • Now navigate to localhost:3000/movies and observe the Routing Error page. This error is expected—generating a controller creates the class file but doesn't automatically configure URL routing. Rails routing is explicit and intentional, giving you complete control over your application's URL structure and preventing accidentally exposed functionality.

  • The routing system bridges the gap between URLs and controller actions. When users request localhost:3000/movies, Rails consults the routing configuration to determine which controller and action should handle the request. Let's configure this routing now.

  • Open the flix folder in your preferred code editor. Modern editors like Visual Studio Code, RubyMine, or Sublime Text provide syntax highlighting, auto-completion, and Rails-specific features that significantly improve development efficiency.

  • In your code editor, open flix > config > routes.rb. This file is the central routing configuration for your entire application.

  • Replace all the commented-out code with the following route definition:

    Rails.application.routes.draw do
       get 'movies' => 'movies#about'
    end

    This route declaration tells Rails to respond to GET requests for the /movies path by calling the about action (method) in the MoviesController class. The => syntax creates this mapping relationship, effectively saying "route GET /movies to MoviesController#about".

  • Save the file and switch back to your browser.

  • Navigate to localhost:3000/movies or reload the page. You'll see a new error message—progress! Rails now recognizes the movies route but reports that the about method doesn't exist in MoviesController. This step-by-step error resolution is typical in Rails development, with each error message guiding you toward the solution.

  • Open flix > app > controllers > movies_controller.rb in your code editor.

    Examine the file structure: MoviesController is a Ruby class that inherits from ApplicationController. This inheritance chain provides extensive functionality—ApplicationController (located in application_controller.rb) inherits from ActionController::Base, which implements request handling, parameter processing, rendering capabilities, security features, and much more. This inheritance eliminates thousands of lines of boilerplate code from your application.

  • Add the about method to your controller:

    class MoviesController < ApplicationController
       def about
       end
    end

    This empty method demonstrates Rails' "Convention over Configuration" philosophy. When a controller action completes without explicitly rendering a response, Rails automatically looks for a view template matching the action name. This implicit behavior reduces code complexity while maintaining predictable functionality.

  • Save the file and reload localhost:3000/movies in your browser.

    The new error message indicates that Rails can't locate a template for the about action. Rails is searching for view templates in conventional locations based on the controller and action names. This automatic template resolution is part of Rails' magic—it reduces configuration while maintaining flexibility.

    Every public method in a Rails controller expects to render some form of response, whether HTML, JSON, XML, or redirects to other actions. The framework's built-in intelligence, inherited from ActionController::Base, handles this automatically when you follow naming conventions.

  • Let's create the missing view template. In your code editor, create a new file.

  • Add the following HTML content:

    <h1>About Flix</h1>
    <p>Flix is all about movies!</p>

    This simple content will verify that our complete MVC chain is functioning correctly. In production applications, view templates combine static HTML with dynamic Ruby code to create rich, data-driven interfaces.

  • Choose File > Save As from your editor menu.

  • Navigate to flix > app > views > movies directory.

  • Save the file as about.html.erb. The .html.erb extension indicates this is an ERB (Embedded Ruby) template that can contain both HTML and Ruby code.

  • Return to your browser and reload localhost:3000/movies.

    Success! Your Flix application now displays the about page, demonstrating a complete request-response cycle through the MVC architecture. You've created what Rails calls a non-resourceful route—a custom route for specific functionality. As we progress, you'll learn about resourceful routes that automatically generate standard CRUD (Create, Read, Update, Delete) operations with minimal code.

    The current appearance is intentionally minimal—Rails focuses on functionality over aesthetics in its default state. Professional Rails applications implement comprehensive design systems, responsive layouts, and sophisticated user interfaces. Styling and design implementation will be our focus in the next exercise, where we'll transform this basic structure into a polished web application.

  • In Terminal, press CTRL+C to stop the development server when you're ready to continue.

  • Generated Controller Files and Their Purpose

    0/5
    Why Use Rails Generate?

    Rails generate ensures correct file naming and placement, which is critical for Rails applications to function properly. It saves significant time compared to manual file creation.

    Key Takeaways

    1MVC architecture separates Rails applications into three distinct components: Models (data storage), Views (user interface), and Controllers (request routing)
    2Rails uses specific frameworks for each MVC component: ActiveRecord for models, ActionView for views, and ActionController for controllers
    3The 'rails new' command creates a complete Rails application structure with all necessary directories and configuration files
    4Controllers bridge models and views by receiving requests, fetching data from models, and passing it to views for display
    5The 'rails generate controller' command creates essential files including the controller class, view directory, test files, and helper files
    6Proper file naming and directory structure is critical in Rails - files must be in exact locations with correct names to function
    7Routes in config/routes.rb define how URL paths map to specific controller actions using simple syntax like 'get movies => movies#about'
    8Controller methods automatically render views with matching names, inheriting this behavior from ActionController::Base

    RELATED ARTICLES