Skip to content

Instantly share code, notes, and snippets.

@ppdeassis
Last active December 15, 2015 20:11
Show Gist options
  • Save ppdeassis/8837098 to your computer and use it in GitHub Desktop.
Save ppdeassis/8837098 to your computer and use it in GitHub Desktop.
Rails model template
class ContractLink < ActiveRecord::Base
# NOTE: whenever possible, use alphabetic order
# includes/extends
# --
include MyModule
extend MyOtherModule
# class definitions, like gem configurations/initializations
# --
# example, if using paper_trail gem
has_paper_trail
# kaminari (pagination)
paginates_per 20
# constant definitions
# --
CONSTANT_TYPES = [:one, :two, :other]
MIN_PROFIT = 30_000
STATUSES = { ready: 1, scheduled: 2, running: 3, success: 4, failure: 5 }
# callbacks (order: http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html)
# --
after_initialize :defaults, if: :new_record?
after_commit :notify
# associations, grouped by "kind" (belongs_to, has_one, has_many...) in a "priority" order (belongs, one, many)
# --
# NOTE: :some before :that because of alphabetical order
belongs_to :some
belongs_to :that
has_one :thing
has_many :tags
# attributes section
# --
# rails version 3.x
attribute_accessible :description, :income, :kind, :name,
:status, :that_attributes
# enum: rails >= 4.1 (http://edgeapi.rubyonrails.org/classes/ActiveRecord/Enum.html)
enum status: STATUSES
# nested attrs
accepts_nested_attributes_for :that, allow_destroy: true
# validations section
# --
# NOTE: Order validations by attribute/association name.
#
# NOTE2: Let's try to use one `validates` per attribute, so we can easily
# check what's been validates for each attribute.
#
# wrong:
# validates_uniqueness_of :name
# validates_presence_of :name
#
# right:
# validates :name, presence: true, uniqueness: true
#
validates :income, numericality: { greater_than_or_equal_to: 0 }
validates :kind, numericality: { only_integer: true,
greater_than_or_equal_to: 0,
less_than: CONSTANT_TYPES.size }
validates :name, presence: true, uniqueness: true
# Association presence is validated through association name (not association_id attribute!)
validates :some, presence: true
# IMPORTANT: this is not necessary if using `enum` (rails 4.1+)
validates :status, in: STATUSES.values
# custom validations
validate :special_check
# associated models with nested attributes
validates_associated :that
# class methods (like scopes)
def self.special
where(kind: 'special')
end
# instance methods
def positive?
income > MIN_PROFIT
end
# private stuff (two lines separating it)
private
# Almost all callback method should be private.
# That's true for custom validation methods too.
def defaults
# this method will run for newly initialized records.
# it can be used to set default values.
self.status ||= :ready
end
def notify
send_income_changed_message_to(Person.managers) if income_changed?
send_something_else_to(Person.project_leaders)
end
def special_check
# note that this error message get's automatically translated to
# activerecord.errors.models.contract_link.attributes.that.invalid (if defined)
# falling back to default activerecord.errors.invalid ('is not valid').
errors.add(:that, :invalid) unless that.active?
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment