# Models
> The fundamental block of the MVC pattern. Let&#39;s learn what they are and best practices

In general, the term “model” refers to a representation of an object, a person, or a system.

In Rails, it's the root of the Model-View-Controller, or MVC, the architectural pattern generally used to develop user interfaces that's also used by the framework.

Their elemental function is to represent the data structure and business logic of an application while being able to access data stored in the database.

But that's not the only role they play in Rails. Let's see what are their main responsibilities:
## Rails models responsibilities
Even if the function of models can be supplemented by other objects in some design patterns, in Rails, models have a couple of distinct responsibilities:
### Data representation and persistence
Typically, models correspond to tables in the database following Rails conventions.

Each instance of the model represents a row in the table that, by convention, receives the name of the model but pluralized: The `User`model corresponds to the `users` table.

Mainly, Rails models inherit behavior from `ApplicationRecord` which implements the Active Record ORM (Object-Relational Mapping) to facilitate the relation with the data stored in the database.

Active Record provides an easy-to-use interface for:

- **Object mapping:** in charge of mapping database tables to Ruby objects: database records become Ruby objects that have attributes that map to the db tables.
- **Performing CRUD operations:** creating, reading, updating and deleting records.
- **Entity relationships:** AR provides an easy way to define how data relates to each other.
- **Validations:** ensuring data is valid before it's saved to the database. This can be performed at the database level, but Rails offers an extra way of achieving the same outcome.
- **Callbacks:** lifecycle hooks that we can use to execute code at specific points of the object's life: before or after validations are performed or the object is saved to the database.
- **Scopes:** provide a way to retrieve collections of records with specific requirements using the ORM, Arel or plain SQL.
### Business Logic
Besides object mapping and accessing the database, Rails models are used to encapsulate our application's business logic, which is the code that's specific to our application or business domain.

If we're building a SaaS app, we might need logic to see if a `User` is subscribed or on a trial using our specific requirements.

It represents the rules, processes, and constraints that define how our application operates based on the requirements or our user's needs.

When using models, the logic is usually implemented using tools like custom methods, validations, [associations](https://avohq.io/glossary/associations), callbacks, etc.

We're also encouraged to use Ruby classes, also known as Plain-Ol'-Ruby-Objects, to represent entities in our application's domain that are not necessarily backed by a database.
### Data relationships
Models are also in charge of the way data is connected by using the relational nature of SQL, which enforces those relationships using **primary and foreign keys**.

In Rails, we can define associations using the following methods:

- `has_many`: indicates a one-to-many relationship. For example, an `Author` can have many books represented by the `Book` model.
- `belongs_to`: is the inverse relationship. A book belongs to an author via a foreign key which, by convention, should be an `author_id` defined in the `Book` model.
- `has_one`: indicates a one-to-one relationship. Like a user who has a `Profile`. 
- `has_and_belongs_to_many`: indicates a many-to-many relationship where we have an intermediate table, but we don't define a model. For example, a `Post` has many tags and, at the same time, a `Tag` can belong to many posts. To achieve this, we need a table called `post_tags` by convention and define the `has_and_belongs_to_many` in both models.
- `has_many :through`: indicates a many-to-many relationship, but we have a model to represent it. For example, we could have a `PostTag` or `PostTagging` model, where we would add a `belongs_to` association to both posts and tags. Meanwhile, we would declare the `has_many :through` in both models, providing us with access to the list of tags for a given post or a list of posts where a given tag was used.
## Model feature implementation
The following are common ways of implementing the Rails model features explained above:
### Validations
They allow us to ensure data integrity in the application itself, and they should be accompanied by database constraints to avoid data corruption:

```ruby
class User < ApplicationRecord
  validates :email, presence: true, uniqueness: true
  validates :username, presence: true, length: {minimum: 6, maximum: 50}
end
```

The validations above require an `email` and `username` to be present to persist a user to the database, but they also require the username to be unique and the length of the `username` to be at least 6 and at most 50 characters.

Rails includes many validations by default, but we can also define a custom validation using the `validate` method:

```ruby
class User < ApplicationRecord
  validate :minimum_age

  private
  def minimum_age
    return if date_of_birth.blank?
    
    if date_of_birth > 18.years.ago.to_date
      errors.add(:date_of_birth, "You must be at least 18 years old")
    end
  end  
end
```

### Callbacks
They allow us to execute code between the object's lifecycle:

```ruby
class Article < ApplicationRecord
  before_save :normalize_title

  private

  def normalize_title
    self.title = title.downcase.titleize
  end
end
```

The code above makes sure our article's title is normalized before being saved to the database.

Rails provides us with many callbacks that allow us to execute code when an object is being created, updated, destroyed or associated with other objects via associations.
### Scopes
They are a way to retrieve a subset of records or sort them using a given criterion.

We can use Active Record, SQL, or even Arel to achieve our goal:

```ruby
class Product < ApplicationRecord
  scope :recent, -> { order(created_at: :desc) }
  scope :by_price_ascending, -> { order(price_cents: :asc) }
  scope :active, -> { where(active: true) }
end
```

We use the `order` method to sort records and `where` to query our database.

We can also use raw SQL if it suits us:

```ruby
class User < ApplicationRecord
  scope :active_last_week, -> { where("last_login_at >= ?", 1.week.ago) }
end
```

Or **Arel** which is a helper library that helps Rails build SQL queries that we can also use:

```ruby
class User < ApplicationRecord
  scope :active_last_week, -> {
    where(Arel::Table.new(:users)[:last_login_at].gteq(1.week.ago))
  }
end
```

## Rails models best practices
Even though models are a special type of object that inherits from `ApplicationRecord`, most of the OOP design advice applies to them.

The following is advice that's usually given when talking about models:

- **Single responsibility principle:** models should focus on a single entity and the aspects that are related to it. For example: a `User` should not be _too worried_ about subscription or payment logic. Otherwise, it usually means we're missing an object to model those other entities.
- **Fat models and skinny controllers:** this is a common motto that was frequently used when Rails came out. It means that, given the choice, we should prefer to put business logic in models and not in [controllers](https://avohq.io/glossary/controllers). There are many other design choices that can improve this simplified vision of application design, but it's a great starting point, especially when compared to alternatives like doing most work in controllers.
- **DRY or Don't Repeat Yourself:** reusing code is encouraged. The DRY principle centers around the fact that duplicate code can become an issue in the future, so it promotes the use of reusable code. In Rails, we can use concerns or—more rarely—inheritance to achieve this goal.
- **Unit and integration testing:** adding tests to make sure our models work like intended is desirable. Automated tests might seem like a drag at first but they pay for themselves almost invariably in the long term.

