Search
⌘K
    to navigateEnterto select Escto close

    Order of items on Active Record models

    In this chapter we are going to discuss how Active Record 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.freeze
    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.freeze
    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 :name, presence: true, length: { maximum: 35 }
    11  validates :email,
    12    presence: true,
    13    uniqueness: true,
    14    length: { maximum: 50 },
    15    format: { with: VALID_EMAIL_REGEX }
    16  validates :password,
    17    presence: true,
    18    confirmation: true,
    19    length: { minimum: 6 }
    20  validates :password_confirmation, presence: true, on: :create
    21
    22  before_save :to_lowercase
    23
    24  private
    25
    26    def to_lowercase
    27      email.downcase!
    28    end
    29end

    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"
    Previous
    Next