Learn Ruby on Rails Book

Order of items on ActiveRecord models

In this chapter we are going to discuss how ActiveRecord models should be structured.

Let's start by looking into the unordered definition of the User model, which will work, but has the potential to cause a lot of harm and debugging issues in the future.

Note that the following is an example of how we shouldn't structure our model:

1class User < ApplicationRecord
2
3  def to_lowercase
4    email.downcase
5  end
6
7  before_save :to_lowercase
8
9  VALID_EMAIL_REGEX = /\A([\w+\-].?)+@[a-z\d\-]+(\.[a-z]+)*\.[a-z]+\z/i
10  validates :email,
11    presence: true,
12    length: { maximum: 255 },
13    format: { with: VALID_EMAIL_REGEX },
14    uniqueness: { case_sensitive: false }
15
16  validates :first_name, presence: true, length: {maximum: 50}
17  validates :last_name, presence: true, length: {maximum: 50}
18end

Items should be presented in an order

Above code works but the Rails community has agreed upon certain order in which items should be presented. And the order goes something like this.

  • default_scope
  • constants
  • attr_*
  • enum
  • associations
  • validations
  • callbacks
  • other macros (like devise's, has_secure_password) should be placed after the callbacks
  • public methods
  • private methods

The RuboCop Rails style guide is a good reference for this.

Now we can rearrange the above to look like this:

1class User < ApplicationRecord
2  VALID_EMAIL_REGEX = /\A([\w+\-].?)+@[a-z\d\-]+(\.[a-z]+)*\.[a-z]+\z/i
3  validates :email,
4    presence: true,
5    uniqueness: { case_sensitive: false }
6    length: { maximum: 255 },
7    format: { with: VALID_EMAIL_REGEX },
8
9  validates :first_name, presence: true, length: {maximum: 50}
10  validates :last_name, presence: true, length: {maximum: 50}
11
12  before_save :to_lowercase
13
14  private
15
16  def to_lowercase
17    email.downcase
18  end
19end

Let's take a look at the User model in our Granite application. If you recall we updated the User model in Adding comments to a task chapter to:

1class User < ApplicationRecord
2  VALID_EMAIL_REGEX = /\A([\w+\-].?)+@[a-z\d\-]+(\. :a-z]+)*\.[a-z]+\z/i.freeze
3
4  has_many :comments, dependent: :destroy
5  has_many :tasks, dependent: :destroy, foreign_key: :user_id
6
7  has_secure_password
8  has_secure_token :authentication_token
9
10  validates :email,
11    presence: true,
12    uniqueness: true,
13    length: { maximum: 50 },
14    format: { with: VALID_EMAIL_REGEX }
15  validates :password,
16    presence: true,
17    confirmation: true,
18    length: { minimum: 6 }
19  validates :password_confirmation, presence: true, on: :create
20
21  before_save :to_lowercase
22
23  private
24
25    def to_lowercase
26      email.downcase!
27    end
28end

We can see that all the items are in correct order inside the User model.

Ideally, we should go through all our models and make sure that the ordering is taken care of. But for the time being let's focus on creating our application.

In the upcoming chapters let's try to add Rubocop rules which can do this job or at least warn us, when ordering is not correct.

After going through the User model and refactoring it (if required), commit the changes:

1git add -A
2git commit -m "Fixed order of items in ActiveRecord models"
⌘K
    to navigateEnterto select Escto close
    Previous
    Next