-
-
Save Nitemaeric/3eb337823741b23b0ecc01f7d51fac23 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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