Altcademy - a Forbes magazine logo Best Coding Bootcamp 2023

What is Model-View-Controller (MVC) in Ruby on Rails?

Model-View-Controller (MVC) is a design pattern that separates the application logic into three interconnected components. This pattern helps in organizing the code in a clean and maintainable way. In this blog, we will explore the MVC pattern, its components, and how it is used in Ruby on Rails, a popular web development framework.

1. Introduction to MVC

When learning programming, it's essential to write clean and organized code. It makes the code easier to understand, maintain, and extend. One way to achieve this is by using design patterns. A design pattern is a reusable solution to common problems that occur in software design. One such design pattern is the Model-View-Controller (MVC).

Imagine you are building a web application to manage a library. The application allows users to search for books, view book details, and reserve books. To build this application, you need to handle data (books, authors, etc.), display the information in a user-friendly way, and respond to user actions (searching, reserving, etc.). These concerns can be separated into three components: Model, View, and Controller.

2. Model

The Model is responsible for managing the application's data and business logic. It represents the underlying structure of the data and defines how it should be stored, retrieved, and manipulated. The Model also enforces the application's rules and constraints.

For our library application, the Model would represent the books, authors, and reservations. It would define how books are added, searched, and reserved.

Here's a simple example of a Book model in Ruby:

class Book
  attr_accessor :title, :author, :status

  def initialize(title, author, status = "available")
    @title = title
    @author = author
    @status = status
  end

  def reserve
    if @status == "available"
      @status = "reserved"
      true
    else
      false
    end
  end

  def return_book
    if @status == "reserved"
      @status = "available"
      true
    else
      false
    end
  end
end

In this example, the Book class has three attributes: title, author, and status. It also has two methods: reserve and return_book. These methods enforce the rules for reserving and returning books.

3. View

The View is responsible for presenting the data to the user. It defines how the information should be displayed and formatted. The View is also responsible for receiving user input and passing it to the Controller.

For our library application, the View would display the list of books, book details, and reservation forms. It would also handle user input, such as searching for a book or reserving a book.

Here's an example of a simple View for displaying a list of books in HTML:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Library</title>
</head>
<body>
  <h1>Books</h1>
  <ul>
    <% books.each do |book| %>
      <li><%= book.title %> by <%= book.author %></li>
    <% end %>
  </ul>
</body>
</html>

In this example, the View uses Ruby's ERB (Embedded Ruby) to loop through an array of Book objects and display their title and author in an unordered list.

4. Controller

The Controller is responsible for coordinating the Model and View. It receives user input from the View, processes it, updates the Model, and updates the View with the new data. The Controller acts as a bridge between the Model and View, ensuring that they remain separate and focused on their specific responsibilities.

For our library application, the Controller would handle user actions such as searching for a book, viewing book details, and reserving a book. It would update the Model with the results of these actions and update the View to display the new information.

Here's an example of a simple Controller for our library application in Ruby:

class LibraryController
  def index
    @books = Book.all
    render "index"
  end

  def search(query)
    @books = Book.search(query)
    render "search_results"
  end

  def reserve(book_id)
    book = Book.find(book_id)
    if book.reserve
      render "reserve_success"
    else
      render "reserve_failure"
    end
  end
end

In this example, the LibraryController has three methods: index, search, and reserve. Each method retrieves or updates data through the Book model, and then renders a corresponding View to display the results.

5. MVC in Ruby on Rails

Ruby on Rails is a web development framework that follows the MVC pattern. Rails provide conventions and tools for organizing your code into Models, Views, and Controllers, making it easy to build clean and maintainable web applications.

In Rails, each component of the MVC pattern has a specific folder:

  • Models are stored in the app/models folder.
  • Views are stored in the app/views folder, organized by controller.
  • Controllers are stored in the app/controllers folder.

Let's see how our library application would be structured in Ruby on Rails.

Model

To create a Book model in Rails, you would use the following command:

rails generate model Book title:string author:string status:string

This command generates a Book model with title, author, and status attributes. The model file would look like this:

# app/models/book.rb
class Book < ApplicationRecord
end

You can add custom methods (like reserve and return_book) to the model:

# app/models/book.rb
class Book < ApplicationRecord
  def reserve
    if self.status == "available"
      self.update(status: "reserved")
      true
    else
      false
    end
  end

  def return_book
    if self.status == "reserved"
      self.update(status: "available")
      true
    else
      false
    end
  end
end

View

In Rails, Views are organized by controller. For our library application, we would create a books folder inside the app/views folder. Then, we would create a file called index.html.erb to display the list of books:

<!-- app/views/books/index.html.erb -->
<h1>Books</h1>
<ul>
  <% @books.each do |book| %>
    <li><%= book.title %> by <%= book.author %></li>
  <% end %>
</ul>

Controller

To create a BooksController in Rails, you would use the following command:

rails generate controller Books

This command generates a BooksController with a default index method. You can add the search and reserve methods to the controller:

# app/controllers/books_controller.rb
class BooksController < ApplicationController
  def index
    @books = Book.all
  end

  def search
    @books = Book.where("title ILIKE ?", "%#{params[:query]}%")
  end

  def reserve
    @book = Book.find(params[:id])
    if @book.reserve
      redirect_to @book, notice: "Book was successfully reserved."
    else
      redirect_to @book, alert: "Book could not be reserved."
    end
  end
end

In this example, the BooksController retrieves and updates data through the Book model and renders the corresponding Views.

6. Conclusion

In this blog, we explored the Model-View-Controller (MVC) design pattern and how it is used in Ruby on Rails. By separating the application into Models, Views, and Controllers, the MVC pattern helps you write clean, organized, and maintainable code.

When building web applications, following design patterns like MVC can make a significant difference in the long run. It allows you to focus on individual components without becoming overwhelmed by the complexity of the entire application. So, keep practicing, and always strive to write clean and organized code. Happy coding!