# Convention Over Configuration
> A term coined by DHH, Rails framework creator, that states a great preference to use as many convened upon decisions over the extensive use of configuration and customization before hand.

As a part of the Rails Doctrine, **Convention over Configuration** is a set of guidelines and defaults set by the framework to make development faster and more efficient.

It's one of the core design philosophies behind Rails: providing sensible defaults allows developers to focus on what makes the application unique instead of spending too much time writing configuration or boilerplate code.

As it usually happens, the philosophy came to life as a response to the configuration and boilerplate-heavy web applications that dominated the scene when the framework was created.

Part of the joy of removing the boilerplate can be appreciated in the famous [15-minute blog video](https://avohq.io/glossary/15-minute-blog) that DHH made when presenting the framework in 2005.

Let's explore some Rails conventions:
## Conventions
In the context of Rails, a convention is an agreed-upon or designed way to achieve things. Conventions are documented but frequently implicit.

For example: if we create a new model, a migration is added that will create a table for the model in its plural form: the `Message` model gets the `messages` table. 
### Autoloading
Maybe the convention that causes the most confusion: Rails autoloads classes based on the file system path. 

There's no need to import them explicitly. If we add a `Comment` class in the `models` directory, we can use that class anywhere because Rails loads it when the class is referenced.

If you've used Ruby before, you probably know that you need to require dependencies explicitly:

```ruby
require "message"

message = Message.new(body: "Hello, World!")
```

That's not the case with Rails: classes and modules are available everywhere without the `require` calls.

If we have a `User` model defined in `app/models` we can just reference it in a controller without requiring anything:

```ruby
class PostsController < ApplicationController
  def index
    user = User.first
    @posts = user.posts.published
  end
end
```

In this example, without autoloading, we would need to require the `ApplicationController` class, as well as the `User`.

For this purpose, Rails uses [Zeitwerk](https://github.com/fxn/zeitwerk) and sets some loaders which provide autoloading, reloading and eager loading.
### File and class naming
The next convention that can be confusing at first is the way file and class naming is used to map behavior.

In [models](https://avohq.io/glossary/models), class names use camel case in singular. For example, `UserInteraction` maps to the `user_interaction.rb` file and to the `user_interactions` database table.

Controllers behave similarly, class names use camel case, but every class in the `controllers` directory has the `controller` suffix, and it conventionally matches to the model using the plural form. For the previous example, the controller would be `UserInteractionsController` and live under `app/controllers`.

Function names, also called actions in the controller context, use snake case: `first_name`, `show`, `destroy`, etc.

When it comes to **tests,** they live in the `test` directory. Different types of test live within a subdirectory like `test/models` or `test/controllers` and each test class where actual tests are defined has `test` as a suffix: `article_test.rb`.

Many gems extend these types of conventions to make their own. For example, the [pundit gem,](https://github.com/varvet/pundit) an authorization library for Ruby and Rails apps, defines the authorization rules inside policy files. These files live in the `policies` directory, they reference a resource and its name ends in `policy`. For example: `PostPolicy`.

{{info}}
Almost any convention can be overridden by configuration if it makes sense. However, besides writing clean code, sticking as close as possible to Rails defaults is usually a good practice to help other developers work with our codebase and make the upgrade process easier.
{{/info}}
### Database
Besides the naming convention, foreign key relationships follow a pattern too.

An `Article` model that belongs to a user should have a `user_id` column in the `articles` table. Then, we can add the [association](https://avohq.io/glossary/associations) using the `belongs_to` method.

Primary keys default to an auto-incrementing `id` column, and, when creating resources with Rails commands like the model, migration or scaffold generators, two useful timestamp columns `created_at` and `updated_at` are added automatically.

Another thing that Rails does implicitly that involves the database is that it defines a series of methods for each table column using metaprogramming: getters and setters and many helper methods. Boolean fields also get a corresponding method with a `?` sign.

For example, a `published` boolean field adds a `published?` method that returns the boolean status.
### Routes
Rails follows RESTful routing conventions that map HTTP verbs to controller actions automatically. When we add `resources :posts` to our routes file, Rails creates seven standard routes without additional configuration.

These routes follow a predictable pattern: `GET /posts` maps to the `index` action, `GET /posts/:id` maps to `show`, `POST /posts` maps to `create`, and so on. The controller actions are expected to be named accordingly: `index`, `show`, `new`, `create`, `edit`, `update`, and `destroy`.

Rails also generates helpful path and URL helpers based on the resource name. For a `posts` resource, we automatically get methods like `posts_path`, `post_path(post)`, `new_post_path`, and `edit_post_path(post)` that we can use in views and controllers without defining them explicitly.

Nested routes follow similar conventions. If we have posts that belong to users, we can write `resources :users do resources :posts end` and Rails will create routes like `/users/:user_id/posts` that map to the same controller actions but with the parent resource context.
### Views
By default, [views](https://avohq.io/glossary/views) are files that live in the `app/views` directory and each one of them matches to an action in the controller for its corresponding resource.

For example, if we have:

```ruby
class PostsController < ApplicationController
  def index
    @posts = Post.all
  end
end
```

Conventionally, we should have an `index.html.erb` view inside the `app/views/posts` directory.

However, the opposite is not true: we can define controller actions that don't match to views like the: `create` action which is generally in charge of creating a given resource or entity.

The other convention that can seem magical at first is that instance variables defined in controllers are available in views without the need for us to do anything.

This means that we can use the `@posts` in our `index`view:

```erb
<%# app/views/posts/index.html.erb %>
<% @posts.each do |post| %>
  <p><%= post.title %></p>
<% end %>
```
### Associations
Active Record associations also use naming conventions to establish relationships between models with minimal configuration.

For example, consider the following association:

```ruby
class User < ApplicationRecord
  has_many :posts
end

class Post < ApplicationRecord
  belongs_to :user
end
```

With the `belongs_to :user` macro call, Rails expects a `user_id` in the posts table, and it automatically adds instance methods like `post.user` which will retrieve the associated user instance, `post.user=` which can help us set the user for a Post instance. Inverse methods in the `User` model are also defined: `user.posts` to retrieve posts associated to the user or `user.posts.build` to create a new `Post` in memory that's associated to the user instance via the `user_id`.

However, when decide to customize some things, we can achieve that via configuration:

```ruby
class Post < ApplicationRecord
  belongs_to :author, class_name: "User", foreign_key: :author_id
end
```

This goes to show that we can customize things when it makes sense, but we should try to keep customizations to a minimum to avoid deviating too much from expectations.
## Configuration
The opposite of the **Convention Over Configuration** approach Rails embraces is a configuration-centered approach, which gives developers the ability to structure the application and its moving parts to their liking.

It implies making many decisions before `Hello, World!` and it also requires experience, good judgment and the ability to future-proof the choices.

Even though its name implies writing more configuration, which is often true, it's also about deciding things like software architecture, libraries, standards, etc.

For example, some developers dislike Active Record as an ORM, or they even dislike ORMs altogether, but they might enjoy Ruby as a language, so they prefer to use alternative frameworks that are much more configurable and less opinionated in the way things should be done.

As it typically happens when making these decisions, there's a balance to be made between the pros and cons of each approach, particularly if the product we want to build should survive the short term.

{{warning}}
A configuration-centric approach can make for a custom and more enjoyable experience, but consider that dependencies are liabilities and that moving away too far from standards can produce issues eventually.
{{/warning}}
## Criticisms
When properly understood, the Convention over Configuration principle is probably one of the main strengths of Rails.

However, because most of the conventions are implicit, some people find that using Rails feels like magic and that finding where behavior comes from can be overwhelming.

This is especially true for developers that have extensive experience with languages that favor explicit behavior. Their initial exposure to Rails can make them feel lost or confused.

The other branch of criticism to the principle comes from the fact that onboarding developers to a big Rails codebase can become an issue if the new developers are not very familiar with the framework, which can make hiring harder when compared to other frameworks.

Considering that, even if it feels magic at times, Rails is just Ruby, learning about the language and how the framework uses it to build its own constructs can greatly help understand where the conventions come from, learn to embrace them unless there's a specific reason not to, and be more productive with the framework than with alternatives.
## Summary
Rails was born in an era where extensive configuration and boilerplate code were required before starting to produce useful applications.

In that context, the framework leveraged Ruby and some of its unique features to make developers more productive by abstracting some repeating behavior into sensible and opinionated defaults that made sense for most application, most of the time.

The Convention over Configuration principle, which is a part of what makes Rails [omakase](https://avohq.io/glossary/omakase), involves many decisions and things that Rails does implicitly which can make developers more productive by contemplating scenarios that are common to most applications.

As long as we strive to learn about them and stick to Rails conventions, our experience with the framework will be more enjoyable in the long term. 

Of course, if you're not comfortable with the approach and you prefer things to be explicit most of the time, Rails is probably not for you and there are many other options that will better fit your taste.

