DEV Community

Lam
Lam

Posted on

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

Top comments (0)