[Rails] Model

Tags
Rails
Engineering
Created
Oct 14, 2023 04:07 AM
Edited
Oct 13, 2023
Description
Model: scope, validation, callbacks

scope

  • scope is just like macro: allows you to specify commonly-used queries which can be referenced as method calls on the association objects or models
class Book < ApplicationRecord
  scope :out_of_print, -> { where(out_of_print: true) }
end

irb> Book.out_of_print
=> #<ActiveRecord::Relation> # all out of print books

Validation

class Book < ActiveRecord::Base
   belongs_to :subject
   validates_presence_of :title
   validates_numericality_of :price, :message=>"Error Message"
end

validates

class User < ApplicationRecord
  validates :name, presence: true
end

irb> user = User.new
irb> user.save
=> false
irb> user.save!
# ActiveRecord::RecordInvalid: Validation failed: Name can't be blank

Not null and not empty string

class User < ApplicationRecord
  validates :name, presence: true, allow_blank: false
end

Conditional validates

class User < ApplicationRecord
  validates :name, presence: true, unless: -> { is_alvin == true }
end

uniqueness

The column should be unique and no duplicate.
class Account < ApplicationRecord
  validates :email, uniqueness: true
end
Also, with scope, make them a combination:
class Holiday < ApplicationRecord
  validates :name, uniqueness: { scope: :year,
    message: "should happen once per year" }
end
A combination of country and medium is unique.
class AddUniqueIndexToReleases < ActiveRecord::Migration
  def change
    add_index :releases, [:country, :medium], unique: true
  end
end



class Release < ActiveRecord::Base
  validates :country, uniqueness: { scope: :medium }
end

inclusion

class Coffee < ApplicationRecord
  validates :size, inclusion: { in: %w(small medium large),
    message: "%{value} is not a valid size" }
end

callback

  • Callbacks are mainly used around object lifecycle such as create, update, destroy, and etc
  • X_Y
    • X: before, after, and around
    • Y: create, update, save, commit, destroy, rollback
# from https://stackoverflow.com/questions/27932270/how-does-an-around-action-callback-work-an-explanation-is-needed
begin
    # Do before action...
    logger.info 'I am the before action'

    # Do the action, which is passed as a block to your "around filter"
    # Note that if you were to delete this line, the action will never be called!
    yield

    # Do after action...
    logger.info 'I am the after action'
ensure
    raise ActiveRecord::Rollback
end

before_validation

Is called before Validations.validate (which is part of the Base.save call).
# trigger a method
class User < ApplicationRecord
  validates :name, presence: true

	before_validation :callback_name

	def callback_name
		# do something
	end
end



# trigger a block
class User < ApplicationRecord
  validates :login, :email, presence: true

  before_create do
    self.name = login.capitalize if name.blank?
  end
end

# trigger a proc
class User < ApplicationRecord
  before_create ->(user) { user.name = user.login.capitalize if user.name.blank? }
end


# trigger a custom callback object
class User < ApplicationRecord
  before_create MaybeAddName
end

class MaybeAddName
  def self.before_create(record)
    if record.name.blank?
      record.name = record.login.capitalize
    end
  end
end

Related Articles