Skip to content

Instantly share code, notes, and snippets.

@Nitemaeric
Created March 2, 2021 20:29
Show Gist options
  • Save Nitemaeric/3eb337823741b23b0ecc01f7d51fac23 to your computer and use it in GitHub Desktop.
Save Nitemaeric/3eb337823741b23b0ecc01f7d51fac23 to your computer and use it in GitHub Desktop.
class Post < ApplicationRecord
# ==================================================
# Module & Concern Includes
# ----------
# Modules and Conerns tend to add behaviours and
# provide you with new DSL. Adding these at the very
# top prevents you from calling something that might
# not have been defined elsewise.
# ==================================================
include ActsAsStateMachine
include Commentable
# ==================================================
# Constants
# ----------
# Constants are commonly referenced in external
# files. Having these near the very top saves you
# from scrolling to an unknown part of this file.
# ==================================================
ACTIVE_STATES = %i[published]
INACTIVE_STATES = %i[draft discarded]
# ==================================================
# Default Scope
# ----------
# This is defined as high as possible to ensure
# developers are aware of the default scope.
# ==================================================
# Reference here to
# https://github.com/jhawthorn/discard
default_scope { kept }
# ==================================================
# Callbacks
# ----------
# This is also defined as high as possible to make
# developers aware of data mutations in callbacks.
# ==================================================
before_create :private_method # This method should not be called anywhere else.
after_create do
# Putting this logic into a block makes sure that developers don't need to scroll
# to private methods right at the bottom to see the logic here.
end
# ==================================================
# Non-persistant Attributes
# ----------
# I sneak in attributes here as they are often few
# and fit in nicely as simple properties followed by
# complex associations.
# ==================================================
attribute :attr1, default: false
attr_accessor :attr2
# ==================================================
# Associations
# ----------
# Here is the bulk of most model files. Generally,
# this block of code will create almost a wall of
# text. I try to group these by context when they
# start to feel that way.
# ==================================================
# Core
# --------------------------------------------------
belongs_to :author
# In the case of optional 1-1 associations. Try to put the foreign key on the other table.
has_one :latest_edit, -> { order() }, class_name: 'Edit'
has_one :latest_editor, through: :latest_edit, source: :author
has_many :tags
accepts_nested_attributes_for :tags
# Analytics
# --------------------------------------------------
belongs_to :analytics_container, optional: true
has_many :views
has_many :sessions, through: :views
# ==================================================
# Attachments
# ----------
# If you are using ActiveStorage, you'll find that
# attachments work very similarly to associations.
# Having these next flows nicely.
# ==================================================
has_one_attached :cover
has_many_attached :previews
# ==================================================
# Additional Attribute Helpers
# ----------
# Here I put attribute modifiers and helpers. They
# are not quite as important as new attributes so
# these are defined later on.
# ==================================================
monetize :price_cents
translates :title
# ==================================================
# Validations
# ----------
# Surprisingly enough, validations never were the
# highest priority of a model to me. They were
# necessary parts of the code that faded into the
# background, especially with client side
# validations.
# ==================================================
validates :title, presence: true, length: { minimum: 10, maximum: 80 }
# ==================================================
# Scopes
# -----------
#
# ==================================================
scope :active, -> { where(state: ACTIVE_STATES) }
scope :inactive, -> { where(state: INACTIVE_STATES) }
scope :upcoming, -> (time = Time.current) { where(arel_table[:published_at].gt(time) }
# ==================================================
# Public Instance Methods
# ----------
# These methods should typically be data retrieving helpers.
# ==================================================
def current_catalogue_programming(country:)
catalogue_programmings.available(country: country).first
end
# ==================================================
# Class Methods
# These methods should be global data retrieving helpers.
# ==================================================
# Film.average_rating
# Film.live.average_rating
def self.average_rating
average(:rating)
end
# ==================================================
# Private Methods
# ==================================================
def private_method
# Definiton of the the callback defined above.
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment