Rails Models Cheat Sheet

hoanganhlam

Lam

Posted on May 12, 2021

Rails Models Cheat Sheet

Reference

Overriding accessors

class Song < ActiveRecord::Base
  # Uses an integer of seconds to hold the length of the song

  def length=(minutes)
    write_attribute(:length, minutes.to_i * 60)
  end

  def length
    read_attribute(:length) / 60
  end
end
Enter fullscreen mode Exit fullscreen mode

See: http://api.rubyonrails.org/classes/ActiveRecord/Base.html

Callbacks

  • after_create
  • after_initialize
  • after_validation
  • after_save
  • after_commit### Serialize
class User < ActiveRecord::Base
  serialize :preferences
end
Enter fullscreen mode Exit fullscreen mode
user = User.create(
  preferences: {
    'background' => 'black',
    'display' => 'large'
  }
)

Enter fullscreen mode Exit fullscreen mode

You can also specify a class option as the second parameter that’ll raise an exception if a serialized object is retrieved as a descendant of a class not in the hierarchy.

# Only Hash allowed!
class User < ActiveRecord::Base
  serialize :preferences, Hash
end
Enter fullscreen mode Exit fullscreen mode
# Reading it raises SerializationTypeMismatch
user = User.create(preferences: %w(one two three))
User.find(user.id).preferences

Enter fullscreen mode Exit fullscreen mode

Other tricks### Where interpolation

where('name = ?', 'John')
where(['name = :name', { name: 'John' }])
Enter fullscreen mode Exit fullscreen mode

Joining

# Basic joins
Student.joins(:schools).where(schools: { type: 'public' })
Student.joins(:schools).where('schools.type' => 'public' )
Enter fullscreen mode Exit fullscreen mode
# Multiple associations
Article.joins(:category, :comments)
Enter fullscreen mode Exit fullscreen mode
# Nested associations
Article.joins(comments: :guest)
Enter fullscreen mode Exit fullscreen mode
# SQL
Author.joins(
  'INNER JOIN posts ' +
  'ON posts.author_id = authors.id ' +
  'AND posts.published = "t"'
)
Enter fullscreen mode Exit fullscreen mode

Mass updates

# Updates person id 15
Person.update 15, name: "John", age: 24
Person.update [1,2], [{name: "John"}, {name: "foo"}]
Enter fullscreen mode Exit fullscreen mode

Callbacks

record.errors.valid?      # → false
record.errors             # → { :name => ["can't be blank"] }
record.errors.messages    # → { :name => ["can't be blank"] }
Enter fullscreen mode Exit fullscreen mode
record.errors[:name].any?
Enter fullscreen mode Exit fullscreen mode

Other API

Custom validations

class Person < ActiveRecord::Base
  validate :foo_cant_be_nil

  def foo_cant_be_nil
    errors.add(:foo, 'cant be nil')  if foo.nil?
  end
end
Enter fullscreen mode Exit fullscreen mode

Validation

class Person < ActiveRecord::Base
Enter fullscreen mode Exit fullscreen mode
  # Presence
  validates :name,     presence: true
Enter fullscreen mode Exit fullscreen mode
  # Acceptance
  validates :terms,    acceptance: true

Enter fullscreen mode Exit fullscreen mode
  # Confirm
  validates :email,    confirmation: true

Enter fullscreen mode Exit fullscreen mode
  # Unique
  validates :slug,     uniqueness: true
  validates :slug,     uniqueness: { case_sensitive: false }
  validates :holiday,  uniqueness: { scope: :year, message: 'yearly only' }

Enter fullscreen mode Exit fullscreen mode
  # Format
  validates :code,     format: /regex/
  validates :code,     format: { with: /regex/ }

Enter fullscreen mode Exit fullscreen mode
  # Length
  validates :name,     length: { minimum: 2 }
  validates :bio,      length: { maximum: 500 }
  validates :password, length: { in: => 6..20 }
  validates :number,   length: { is: => 6 }

Enter fullscreen mode Exit fullscreen mode
  # Include/exclude
  validates :gender,   inclusion: %w(male female)
  validates :gender,   inclusion: { in: %w(male female) }
  validates :lol,      exclusion: %w(xyz)

Enter fullscreen mode Exit fullscreen mode
  # Numeric
  validates :points,   numericality: true
  validates :played,   numericality: { only_integer: true }
  # ... greater_than, greater_than_or_equal_to,
  # ... less_than, less_than_or_equal_to
  # ... odd, even, equal_to

Enter fullscreen mode Exit fullscreen mode
  # Validate the associated records to ensure they're valid as well
  has_many :books
  validates_associated :books

Enter fullscreen mode Exit fullscreen mode
  # Length (full options)
  validates :content, length: {
    minimum:   300,
    maximum:   400,
    tokenizer: lambda { |str| str.scan(/\w+/) },
    too_short: "must have at least %{count} words",
    too_long:  "must have at most %{count} words" }

Enter fullscreen mode Exit fullscreen mode
  # Multiple
  validates :login, :email, presence: true

Enter fullscreen mode Exit fullscreen mode
  # Conditional
  validates :description, presence: true, if: :published?
  validates :description, presence: true, if: lambda { |obj| .. }

Enter fullscreen mode Exit fullscreen mode
  validates :title, presence: true, on: :save   # :save | :create | :update

Enter fullscreen mode Exit fullscreen mode
end
Enter fullscreen mode Exit fullscreen mode

Polymorphic associations

class Post
  has_many :attachments, as: :parent
end
Enter fullscreen mode Exit fullscreen mode
class Image
  belongs_to :parent, polymorphic: true
end
Enter fullscreen mode Exit fullscreen mode

And in migrations:

create_table :images do |t|
  t.references :post, polymorphic: true
end
Enter fullscreen mode Exit fullscreen mode

Validation

💖 💪 🙅 🚩
hoanganhlam
Lam

Posted on May 12, 2021

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related

Your Auth Cheat Sheet
authentication Your Auth Cheat Sheet

September 13, 2022

Vim-Rails Cheat Sheet
vim Vim-Rails Cheat Sheet

May 13, 2021

Rspec-Rails Cheat Sheet
rails Rspec-Rails Cheat Sheet

May 12, 2021