Architecture of Our Rails Application and Its Boundaries

Learn about the key components of a Rails application that includes boundaries, views, and models, and explain their functions in building a Rails project.

Default application architecture

This course contains guidelines, tips, and recipes for managing the architecture of our Rails application as it grows over time, so we want to start with a review of the default application architecture we get with Rails. This architecture is extremely powerful, mostly because it exists right after we run the following command, and it provides a solid way to organize the code in our application.

rails new

Rails is often referred to as an MVC framework, where MVC stands for Model, View, and Controller.

Rails does, in fact, have models, views, and controllers, but digging into the history of MVC and trying to sort out how it relates to Rails can create confusion since the concepts don’t exactly match up. This is OK, we don’t need them to.

We’ll skip the theory and look at the actual parts of Rails and how they contribute to the overall application we build with Rails. Although there are quite a few moving parts, each part falls into one of four categories:

  • Boundaries, which accept input from somewhere and arrange for output to be rendered or sent. Controllers, Mailers, etc., are boundaries.
  • Views, which present information, usually in HTML. ERB files, JavaScript, CSS, and even JBuilder files are all part of the view.
  • Models, which are the Active Record classes that interact with our database.
  • Everything else.

Rails doesn’t talk about the parts this way, but we will since it allows us to group similar parts together when talking about how they work. The below figure shows all the parts of Rails 6 and which of the four categories they fall into. The diagram shows that:

  • The boundaries of our Rails app are the controllers, jobs, mailers, mailboxes, channels, and rake tasks, as well as Active Storage.
  • The view is comprised of ERB, JavaScript, CSS, Images, Fonts, and other assets like PDFs or binary files.
  • The models are, well, our models, and they talk to our database (though a model does not have to talk to a database).
  • Anything not mentioned, like configuration files or our Gemfile, are in the catch-all “Everything else” bucket.
Press + to interact
Rails’ default application architecture
Rails’ default application architecture

Let’s now go through each layer and talk about the parts of Rails in that layer and what they are all generally for. We’ll stay as close as we can to what we believe the intent of the Rails core team is and try not to embellish or assume too much.

First, we’ll start with Boundaries, which broker input and output.

Boundaries

The Rails Guide says that controllers are responsible for making sense of the request and producing the appropriate output.

When we look at Jobs, Channels, Mailers, Mailboxes, Active Storage, and Rake Tasks, they perform similar functions. In a general sense, no matter what else goes in these areas, they have to:

  • Examine the input to make sense of it.
  • Trigger some business logic.
  • Examine the output of that business logic and provide some sort of output or effect.

Of course, not all use cases require reading explicit input or generating explicit output, but the overall structure of the innards of any of these classes, at least at a high level, is the same, as shown in the figure below.

Press + to interact
Structure of a boundary class
Structure of a boundary class

This figure shows that:

  • Some input might come in that triggers the Boundary class.
  • The Boundary class examines that input to see if it understands it.
  • Some business logic happens.
  • The result of that logic is examined.
  • Explicit output is possibly sent.

For now, we’re not going to talk about the business logic, specifically if it should be directly in the boundary classes or not. The point is that, no matter where the business logic is, these boundary classes are always responsible for looking at the input, initiating the logic, and assembling the output.

We’ll talk about these boundary classes in more detail in the following chapters.

Because Rails is for building web applications, the boundary classes, in most cases, will output dynamic/static web views. The web application view layer is complex to create, and Rails has a lot of features for views.