
Model Structure Done Right
I have been writing Ruby on Rails apps for almost a decade now and I've come to notice that my speed of development inversely scales with how many decisions I have to make.
A lot of these decisions come down to lack of structure. But reaching the point where you're comfortable with the final design really is a good feeling.
Here are my opinionated best practices for constructing ActiveRecord models:
class Post < ApplicationRecord
# ==================================================
# Module & Concern Includes
# ==================================================
include ActsAsStateMachine
include Commentable
# ==================================================
# Constants
# ==================================================
ACTIVE_STATES = %i[published]
INACTIVE_STATES = %i[draft discarded]
# ==================================================
# Default Scope
# ==================================================
default_scope { kept }
# ==================================================
# Callbacks
# ==================================================
before_create :private_method
# ==================================================
# Non-persistant Attributes
# ==================================================
attribute :attr1, default: false
attr_accessor :attr2
# ==================================================
# Associations
# ==================================================
belongs_to :author
has_one :latest_edit, -> { order() }, class_name: 'Edit'
has_many :tags
accepts_nested_attributes_for :tags
# ==================================================
# Attachments
# ==================================================
has_one_attached :cover
has_many_attached :previews
# ==================================================
# Additional Attribute Helpers
# ==================================================
monetize :price_cents
translates :title
# ==================================================
# Validations
# ==================================================
validates :title, presence: true, length: { minimum: 10, maximum: 80 }
# ==================================================
# Scopes
# ==================================================
scope :active, -> { where(state: ACTIVE_STATES) }
scope :inactive, -> { where(state: INACTIVE_STATES) }
# ==================================================
# Public Instance Methods
# ==================================================
def current_catalogue_programming(country:)
catalogue_programmings.available(country: country).first
end
# ==================================================
# Class Methods
# ==================================================
def self.average_rating
average(:rating)
end
# ==================================================
# Private Methods
# ==================================================
private
def private_method
end
end

