Search code examples
ruby-on-railscoding-styleconventions

What is the correct order of associations, scopes, validations, etc. in Rails models


Edited this old question to include an answer from below: Rubocop has it https://github.com/rubocop-hq/rails-style-guide#macro-style-methods

Rails is all about 'Convention over Configuration'. However, I haven't come across a 'standard' for the order of associations, scopes, includes, validations, ... in Rails models yet. Take for example the following, simplified, product model:

class Product < ActiveRecord::Base
  mount_uploader :logo, AssetUploader
  acts_as_taggable
  paginates_per 50

  include ActionView::Helpers::NumberHelper

  belongs_to :company

  validates_presence_of [:title, :price, :plu]

  scope :on_website, where(display: true)

  def display_price
    ...
  end
end

Is this the correct order? It's maybe not that important to many people, but I personally think it would be great if there were a convention on this.


Solution

  • Rubocop has it https://github.com/rubocop-hq/rails-style-guide#macro-style-methods

    class User < ActiveRecord::Base
      # keep the default scope first (if any)
      default_scope { where(active: true) }
    
      # constants come up next
      COLORS = %w(red green blue)
    
      # afterwards we put attr related macros
      attr_accessor :formatted_date_of_birth
    
      attr_accessible :login, :first_name, :last_name, :email, :password
    
      # Rails 4+ enums after attr macros
      enum gender: { female: 0, male: 1 }
    
      # followed by association macros
      belongs_to :country
    
      has_many :authentications, dependent: :destroy
    
      # and validation macros
      validates :email, presence: true
      validates :username, presence: true
      validates :username, uniqueness: { case_sensitive: false }
      validates :username, format: { with: /\A[A-Za-z][A-Za-z0-9._-]{2,19}\z/ }
      validates :password, format: { with: /\A\S{8,128}\z/, allow_nil: true }
    
      # next we have callbacks
      before_save :cook
      before_save :update_username_lower
    
      # other macros (like devise's) should be placed after the callbacks
    
      ...
    end