View on Github
To-do App Project Showcase
Ruby Rails MVC Architecture ActiveRecord RESTful Routing

To-do App Project Showcase

Charley Yoshi

Charley Yoshi

Posted: July 24, 2023, 8:07 a.m.


I built a simple Todo app using Ruby on Rails. The main goals were to grasp basic Rails concepts, handle CRUD operations (Create, Read, Update, Delete), and make use of the MVC architecture, ActiveRecord, and RESTful routing.

This blog post breaks down the project, highlighting how these elements work together to create an effective and easy-to-use Todo application.

Contents

  1. Why I chose Ruby on Rails
  2. The Model-View-Controller (MVC) Architecture
    1. Model
    2. View
    3. Controller
  3. RESTful Routing
  4. Challenges Faced and Lessons Learned
  5. Conclusion




1. Why I chose Ruby on Rails


I chose Ruby on Rails for these reasons:

  1. Powerful Framework: Ruby on Rails is a powerful and versatile web development framework, and is known for its productivity and community support. Major platforms like GitHub and Airbnb are built on it.

  2. Skill Expansion: After working with Flask and MERN stack, I wanted to expand my skills by diving into a new language and framework.

  3. Learning from Experience: Revisiting an old Node.js project (link to the old repo), I aimed to transform a basic todo list into a whole-stack Rails app, so that I can showcase my growth in my development path.



2. The Model-View-Controller (MVC) Architecture


The backbone of my Todo app lies in the Model-View-Controller (MVC) architecture, a design pattern that is important for developing scalable, efficient and maintainable web applications.

Model

Rails uses ActiveRecord, an ORM (Object-Relational Mapping) system to integrate with the Model, providing an intuitive way to interact with the database. For this app I used two models - the `Todo` model and the `Item` model.

1. Todo Model (Category):
The `Todo` model represents our categories and defines the relationship with the `Item` model, establishing a one-to-many association. This association allows a single category to have multiple tasks. For example, a `todo` record can be `Grocery`. Under `Grocery` there can be multiple items, like `beef`, `onion`, etc.

Here's what the `Todo` model looks like:

MVC - todo model
Image: `models/todo.rb`

The `has_many :items` association establishes a connection between the `Todo` and `Item` models, and the `dependent: :destroy` option ensures that when a category is deleted, all associated tasks (items) are also destroyed.

Below is an example:

Demo - delete whole python todo
GIF: When Study Python is deleted, all items inside are also deleted.

2. Item Model (Task):
The `Item` model represents individual tasks and belongs to a category (`Todo`). It also includes a `before_save` callback to set a default value for the `done` attribute.

Here's what the `Item` model looks like:

MVC - todo model
Image: `models/item.rb`

The `belongs_to :todo` association establishes the connection between the `Item` and `Todo` models, indicating that each task belongs to a specific category.


View

Responsible for presenting the data to the users and capturing their interactions, views are implemented using HTML and embedded Ruby (ERB) templates. These templates dynamically render the data from the controller and provide a user-friendly interface for my Todo app.


`render` vs `redirect_to`

When it comes to rendering views and managing user interactions, Rails provides two key methods: `render` and `redirect_to`.

I used the `render` method to dynamically generate HTML content based on the ERB templates. This allowed me to present data from the controller to the user without a full page reload. For instance, when a form failed to be saved, you want to update the error message but don’t want to lose all the fields the user has already typed in:

MVC - render view demo
GIF: When a form is failed to saved, the existing form input (i.e. description) is not erased.

On the other hand, the `redirect_to` method is useful in managing user navigation and handling actions such as creating, updating, or deleting tasks. For example, after creating a new category:

MVC - redirect view demo
GIF: The page is redirected to show the todo page we just created.

It’s important to know the difference because `render` will pass to the view the same parameters but `redirect_to` will send a completely new request to the browser.


Partials

For a more maintainable and DRY (Don't Repeat Yourself) codebase, I embraced the use of partials in our views. Partials are reusable snippets of ERB templates that can be included in other views. For instance, I created a `_form.html.erb` partial for both the `Todo` and `Item` views to render their respective forms.

Here's a snippet of the `Item` form partial:

View - Partials
Image: Partials - rendering a particular piece of a response to its own file.

Utilizing partials not only simplified the view files but also promoted consistency and reusability across different parts of the application.


Controller

Responsible for handling user requests, Controllers are stored in the `app/controllers` directory. Acting as an intermediary between the Model and View, controllers handle user input, processes it, and updates the Model accordingly. My `TodosController` and `ItemsController` manage CRUD operations for Todo items, ensuring the seamless flow of data between the Model and View.

For instance, when a user adds a new task or marks one as complete, the Controller manages these actions, ensuring that the Model and View remain synchronized.

Todo Controller:

Controller - Todo
Image: Todo Controller

In the `TodosController`, I handle actions such as displaying all categories (`index`), showing a specific category (`show`), creating a new category (`new` and `create`), editing an existing category (`edit` and `update`), and deleting a category (`destroy`). Each action corresponds to a specific view, and the controller ensures that the correct view is rendered or redirected based on the user's interactions.

Item Controller:

Controller - Item
Image: Item Controller

In the `ItemsController`, I handle actions for creating (`create`), updating (`update`), and deleting (`destroy`) tasks. The `create` action redirects to the associated category's show page after creating a task, and the `update` and `destroy` actions also redirect to the category's show page after completing their respective operations.


The MVC architecture not only enhanced the structure of the Todo app but also contributed significantly to its maintainability, scalability, and overall development efficiency.



3. RESTful Routing


RESTful routing is an important concept in Ruby on Rails that defines the way web applications handle HTTP requests. In Ruby on Rails, RESTful routing is built around the idea of treating each component of a web application as a resource, represented by a specific URL path. These resources are manipulated using standard HTTP methods, such as `GET`, `POST`, `PUT`/`PATCH` , and `DELETE`, which correspond to CRUD (Create, Read, Update, Delete) operations. This approach provides a uniform and clear process of designing and maintaining web applications.

Let's delve into the `config/routes.rb` file of my Todo app.

RESTful routing - routes
Image: `config/routes.rb` file

  • The default landing page is the root route (`/`) that points to the `index` action of the `TodosController`, displaying a list of all todo categories.

  • The custom route (`/about`) is mapped to the `/about` action of the `ApplicationController`, providing a dedicated page for information about your application.

  • `resources :todos` generates RESTful routes for the `Todo` resource, automatically creating routes for the actions `index`, `new`, `create`, `edit`, `update`, `show`, and `destroy`.

  • Additionally, by nesting `resources :items` within `resources :todos`, they established a hierarchical relationship, allowing the routes to relate the `items` within a specific `todo`.

Integration with Controllers

Each route defined in `config/routes.rb` corresponds to an action in a controller. For example, when a user accesses the root URL (/), the `index` action of the `TodosController` is triggered. Similarly, when they visit `/todos/new`, the `new` action is called, allowing for the creation of new todo items.

Let's take a closer look at the relationship between the routes and the controller actions:

  • `GET /todos` maps to `TodosController#index` : Displays a list of all todo items.
  • `GET /todos/:id` maps to `TodosController#show`: Displays details of a specific category and all items created under it.
RESTful routing - show christmas
GIF: `GET /todos` and `GET /todos/:id`


And for nested resources:

  • `POST /todos/:todo_id/items` maps to `ItemsController#create`: Add a new item under a specific todo category.
  • `PATCH /todos/:todo_id/items/:id` maps to `ItemsController#update`: Update an item’s status to be done or undone.
RESTful routing - Add item to python
GIF: `POST /todos/:todo_id/items`: Create item Dictionary under todo category Study Python

RESTful routing - Update item update
GIF: `PATCH /todos/:todo_id/items/:id`: Toggle item status between done and undone



4. Challenges-Faced-and-Lessons-Learned


In all honesty, developing a Todo app might seem like a straightforward project, and I didn't encounter major obstacles. Most of the concepts, such as routing and MVC, were already familiar to me from previous frameworks I've worked with, like MERN stack applications.

However, if I were to highlight a challenge, it would be my first experience to the Ruby language itself. As this was my first non-trivial application in Ruby, I invested some time learning the language before even delving into Rails. This included mastering the basics, understanding object-oriented programming (OOP) concepts, and gaining proficiency in file handling and serialization in Ruby. I even practiced those concepts in ruby through projects like Mastermind, Tic-Tac-Toe, and Hangman (links are the github repos to them). As a result, completing this Todo app project significantly enhanced my familiarity and comfort with the Ruby language.

The second noteworthy challenge was adapting to the Rails framework and its principle of `convention over configuration`. Learning to use Rails was a bit tricky. I had to spend a good amount of time reading the guides and documentation to understand how things work. Even though it took some effort, what I learned turned out to be super useful and a great investment. It has become the building blocks for me in being a proficient and confident developer in Rails.



5. Conclusion


In this post, we have explored the key Rails concepts within my Todo app project, including the MVC architecture, ActiveRecord, and RESTful routing.

These concepts are important in building robust and scalable web applications because they provide a structured way to organize code, interact with databases coherently, and define logical and user-friendly routes. As I look forward to future projects, I am excited about the continued learning and expanding my skills in the world of Ruby on Rails.




You've just finished reading: To-do App Project Showcase

To-do App Project Showcase

 

Charley Yoshi

Posted: July 24, 2023, 8:07 a.m.