Web Development with Ruby on Rails

Ruby on Rails is a framework that has revolutionized the way we build modern web applications with speed, structure, and elegance. Today, as part of our Miner’s Guide to Code Crafting series, we will explore it further.

Web development is a crucial area in modern technology, especially with the growing demand for applications that can be accessed from anywhere. Building applications requires attention to various layers, such as the user interface, data storage, and application logic. Each of these components plays a specific role in ensuring everything works seamlessly and effectively.

In this context, Ruby on Rails, or simply Rails, is a web development framework written in Ruby and designed to establish a standard for development teams. Created to streamline and simplify web application development, Rails follows the principle of "Convention over Configuration." This means it provides predefined standards for structuring projects, reducing the number of decisions developers need to make.

MVC

Rails adopts the MVC (Model-View-Controller) pattern to organize code according to specific responsibilities. Each part of MVC corresponds to a layer of the application, each with a distinct role:

Model: Responsible for interacting with the database and managing business logic.

View: Handles the presentation of information to the user.

Controller: Connects models to views, processing requests, and determining what information will be displayed.

Let’s start by looking at how controllers and views work together to handle requests and deliver information in a Rails app.

First things first

When an HTTP request reaches our application, the first point of contact is the routes file, which is responsible for mapping the received URL to a specific controller and action. In Rails, this routes file is located at config/routes.rb and comes pre-configured, allowing developers to adapt it according to the application’s needs. Routes in Rails are defined as follows:

Rails.application.routes.draw do
    get ‘/welcome’, to: ‘home#welcome’
    resources :users
end

In the example above, the first line maps the /welcome URL to the welcome action in the home controller, which handles the request and returns the response to the client.

Additionally, the use of resources simplifies the creation of RESTful routes for a resource called users. This convention automatically generates all the necessary routes for standard CRUD (Create, Read, Update, Delete) operations, such as creating, editing, updating, and deleting users.

For instance, the command resources :users generates routes like:

  • GET /users to list users;
  • POST /users to create a new user;
  • GET /users/:id to display details of a specific user;
  • PATCH/PUT /users/:id to update a user;
  • DELETE /users/:id to delete a user.

These conventions make development faster and more organized, ensuring consistent code structure. The interaction between the application’s routes and controllers is fundamental: when a route is identified, Rails forwards the request to the appropriate controller, which then processes the data and determines the response to send back to the client.

Controllers

Controllers are an essential part of the MVC pattern and are responsible for handling incoming requests and deciding what will be returned to the client. They act as intermediaries between routes, models, and views, connecting the application’s logic with the data needed to generate responses.

Rails provides a straightforward way to create controllers. For example, the following command can be used to generate a controller:

rails generate controller Users index

This command automatically creates a file named UsersController inside the app/controllers directory. Additionally, Rails generates the necessary structure for a view corresponding to the index action. Controllers in Rails follow a convention where each action (or method) handles a specific request. A typical example of a controller would be:

class UsersController < ApplicationController
  def index
    @users = User.all
  end
end

In the example above, the index action is responsible for retrieving all user records from the database using the User.all method and making them available to the corresponding view. The instance variable @users will be used in the view to display the data appropriately.
An important point is that all controllers in Rails inherit from ApplicationController, which provides shared functionality across all controllers in the application. This includes, for example, the ability to apply filters before or after specific actions, such as user authentication.

Controllers also play a vital role in organizing the code, allowing request-handling responsibilities to be separated into different classes. This structure makes the development and maintenance of the application more organized.

Views

After processing, the controller must decide what will be returned to the client. Response options include HTML files, JSON, or even redirects. This is where the V in the MVC pattern comes into play: the views of the application.

Views are responsible for rendering information to the user in a visual format. In Rails, they are directly associated with a controller, which simplifies the transfer of processed data from actions to the presentation layer. This association also establishes a standardized structure, making development more organized and coherent.

The view files in a Rails application are located in the app/views directory. Within this folder, views are organized into subdirectories corresponding to each resource and the actions of the controllers. For example, for the users resource and the index action, the corresponding view file will be app/views/users/index.html.erb.

A typical example of an index.html.erb file would be:

<h1>Users</h1>
<ul>
  <% @users.each do |user| %>
    <li><%= user.name %></li>
  <% end %>
</ul>

In this example, the view file uses the .erb extension (Embedded Ruby), which is the default templating engine in Rails. ERB allows the combination of Ruby code with HTML within the same file. Ruby is embedded using tags for executing code or for displaying values. In the example above, is used to iterate over a collection of users, and is used to display each user’s name in the generated list.

Views generate the HTML sent to the client’s browser, where it is rendered. For instance, in the code above, the browser displays a title and a dynamically generated user list based on the data provided by the controller.

Although ERB is the standard for Rails views, other templating options like HAML and SLIM offer alternative syntaxes for writing HTML and Ruby.

Another important aspect of Rails views is the use of instance variables, like @users in the previous example. These variables are defined in controller actions and are automatically made available to the corresponding view. This seamless integration between controllers and views is one of Rails’ strengths, as it reduces the complexity of sharing data across layers.

Other technologies

In addition to rendering HTML in the client’s browser, web pages often utilize other technologies like CSS and JavaScript to enhance the appearance and behavior of the interface. To manage these resources, Rails offers the Asset Pipeline, an optimized solution for organizing and serving static files.

The Asset Pipeline in Rails is a library designed to organize, optimize, and serve static files such as JavaScript, CSS, and images. It improves performance and maintainability by enabling:

  • Organization: Centralizes and standardizes assets in the app/assets folder.
  • Caching and Compression: Performs minification, concatenation, and fingerprint generation for better performance.
  • Preprocessing: Supports languages like Sass and CoffeeScript.

Importmap-rails is a modern alternative that simplifies JavaScript management in Rails, eliminating the need for tools like Node.js. It leverages native browser support for ES Modules, loading modules directly via “, without requiring bundling or transpiling.

Benefits of importmap-rails:

  • No Node.js or build tools: Dependencies are managed via bin/importmap and hosted on CDNs like jsDelivr.
  • Instant updates: During development, no build step is required, so changes are immediate.
  • Integration with Propshaft: In production, Propshaft optimizes file serving with caching and fingerprinting.

This approach is ideal for applications that use modern JavaScript and do not require complex tools like Babel or Webpack.

Starting with Rails 8, the default asset pipeline is Propshaft. Propshaft is a modern asset pipeline library for Rails, designed for a context where practices like bundling and minification are no longer essential. With the rise of dedicated Node.js bundlers and increased bandwidth, it has become possible to greatly simplify the asset pipeline, replacing more complex tools like Sprockets.

Propshaft offers important features such as configurable load paths, asset digesting for improved production caching, and serving assets directly in the development environment without the need for precompilation.

Conclusion

In summary, Rails is a framework that exemplifies the application of the MVC (Model-View-Controller) pattern, clearly separating the responsibilities of each layer to simplify the development and maintenance of web applications. Controllers process requests and connect the data provided by models to views, which are responsible for dynamically and interactively presenting information to users. The principle of Convention over Configuration promotes an organized and standardized way of designing applications, making development and maintenance more straightforward. Additionally, tools like the Asset Pipeline and importmap-rails enhance the ecosystem, streamlining asset management in true Rails way.

Previously: Full Steam Ahead: Getting Started with Ruby on Rails

This post is part of our ‘The Miners’ Guide to Code Crafting’ series, designed to help aspiring developers learn and grow. Stay tuned for more and continue your coding journey with us!! Check out the full summary here!

We want to work with you. Check out our "What We Do" section!