RoR MVC Pattern

MVC stands for Model, View, Controller. It is the architectural pattern that Rails uses to organize your code. Every file you create in a Rails app fits into one of these three categories. Understanding MVC is the single most important concept in Rails.

The Core Idea: Separation of Concerns

MVC separates your app into three distinct jobs. Each part handles one responsibility and does not interfere with the others.

MVC: Three Rooms, One House

+------------------+      +------------------+      +------------------+
|                  |      |                  |      |                  |
|    MODEL         |      |    VIEW          |      |   CONTROLLER     |
|                  |      |                  |      |                  |
|  Talks to the    |      |  Shows HTML to   |      |  Receives the    |
|  database        |      |  the user        |      |  browser request |
|                  |      |                  |      |                  |
|  Validates data  |      |  Displays what   |      |  Decides what    |
|                  |      |  the controller  |      |  to do           |
|  Stores business |      |  sends it        |      |                  |
|  logic           |      |                  |      |  Asks model for  |
|                  |      |  No data logic   |      |  data, sends to  |
|  No HTML         |      |  here            |      |  view            |
+------------------+      +------------------+      +------------------+

A Real-World Analogy: The Library

You (Browser) walks into a library and asks:
"I want to see all books about cooking."
          |
          v
Librarian (Controller)
  - Receives your request
  - Understands what you want
  - Asks the catalog system for cooking books
          |
          v
Catalog System (Model)
  - Searches the database
  - Returns a list of cooking books
          |
          v
Librarian (Controller)
  - Gets the list from the catalog
  - Prepares it for display
          |
          v
Display Board (View)
  - Shows the list of books to you
  - Formatted, readable, no raw data
          |
          v
You (Browser) sees the final result

How MVC Works in Rails — Step by Step

Here is a concrete example. A user visits http://localhost:3000/posts to see all blog posts.

Step 1: Router receives the request

config/routes.rb
  get "/posts", to: "posts#index"
  
Browser visits /posts → Router reads this line
→ Send this request to PostsController, action: index

Step 2: Controller runs

app/controllers/posts_controller.rb

class PostsController < ApplicationController
  def index
    @posts = Post.all    ← asks the Model for all posts
  end
end

Step 3: Model fetches data

app/models/post.rb
  (inherits from ApplicationRecord which connects to the database)

Post.all
→ Runs: SELECT * FROM posts
→ Returns: array of post objects

Step 4: View displays results

app/views/posts/index.html.erb

<h1>All Posts</h1>
<% @posts.each do |post| %>
  <h2><%= post.title %></h2>
  <p><%= post.body %></p>
<% end %>

The @posts variable (set in the controller) is available in the view. The view loops through each post and displays it as HTML.

Step 5: Browser receives the HTML

Rails combines the view template with the data and sends a complete HTML page back to the browser. The user sees the list of posts.

The @ Symbol: Passing Data from Controller to View

Instance variables (variables starting with @) are the bridge between the controller and the view.

Controller sets:    @posts = Post.all
View accesses:      @posts.each do |post| ...

Controller sets:    @user = User.find(1)
View accesses:      @user.name

Controller sets:    @message = "Welcome back!"
View accesses:      <%= @message %>

Regular local variables (without @) in the controller do NOT reach the view. Only instance variables do.

What Each Part Can and Cannot Do

MVC PartCan DoShould NOT Do
ModelQuery database, validate data, run calculationsGenerate HTML, handle HTTP requests
ViewDisplay data, format HTML, loop through arraysQuery database directly, contain business logic
ControllerReceive requests, call models, pass data to viewsWrite complex queries, contain display logic

Fat Model, Skinny Controller

Rails developers follow a rule called "Fat Model, Skinny Controller." It means: put complex logic in the model, keep the controller simple.

BAD — Logic in controller (too fat):
def index
  @active_users = User.where(active: true).order(:name).limit(10)
  @total_revenue = Order.sum(:amount) * 0.9
end

GOOD — Logic in model (skinny controller):
def index
  @active_users = User.active_list      ← method defined in User model
  @total_revenue = Order.net_revenue    ← method defined in Order model
end

The controller above is easy to read. The logic lives in the model where it can be tested and reused.

Why MVC Makes Your Code Better

  • Easier to find bugs — you know exactly which file to look at for each type of problem
  • Easier to work in teams — one developer works on views while another works on models
  • Easier to test — each part can be tested independently
  • Easier to grow — adding a new feature follows the same structure every time

MVC is not unique to Rails. Django, Laravel, and ASP.NET all use it. Once you understand MVC in Rails, you can quickly learn any other MVC framework.

Leave a Comment

Your email address will not be published. Required fields are marked *