Active Record回调

对象的生命周期

回调可以再对象的状态改变之前或之后触发指定的逻辑操作。

回调简介

回调是在对象生命周期的特定时刻执行的方法。回调方法可以在Active Record对象创建,保存,更新,删除,验证或是从数据库中读出时执行。

注册回调

在使用回调之前,需要先注册。回调方法的定义和普通的方法一样,然后使用类方法注册。

class User < ActiveRecord::Base
  validates :login, :email, presence: true
  
  before_validation :ensure_login_has_a_value

  protected 
    def ensure_login_has_a_value
      if login.nil?
        self.login = email unless email.blank?
      end
    end
end

这种类方法还可以接受一个代码块。如果操作可以使用一行代码表述,可以考虑使用代码块形式:

class User < ActiveRecord::Base
  validates :login, :email, presence: true
   
  before_create do
    self.name = login.capitalize if name.blank?
  end
end

注册回调时可以指定只在对象生命周期的特定事件发生时执行:

class User < ActiveRecord::Base
  before_validation :normalize_name, on: :create

  after_validation: set_location, on: [:create, :update]

  protected
    def normalize_name
      self.name = self.name.downcase.titleize
    end

   def set_location
     self.location = LocationService.query(self)
   end
end

一般情况下,都会把回调方法定义为受保护的或是私有方法。

可用的回调

创建对象

before_validation after_validation
before_save after_save
around_save around_create
before_create after_create

更新对象

before_validation after_validation
before_save after_save
around_save around_update
before_update after_update

销毁对象

before_destroy around_destroy
after_destroy

创建和更新对象都会触发after_save,但不管注册顺序,总在after_create和after_update之后执行。

after_initializeafter_find

after_initialize回调在Active Record对象初始化时执行,包括使用new和从数据库中读取记录。

after_find回调在数据库中读取记录时执行。如果同时注册了after_find和after_initialize回调,after_find会先执行。

after_touch

after_touch回调在碰触Active Record对象时执行。

执行回调 方法触发执行回调

跳过回调 

终止执行

在模型中注册回调后,回调会加入一个执行队列。这个队列中包含模型的数据验证,注册的回调,以及要执行的数据库操作。

整个回调链包含在一个事务中。如果任意一个before_*回调方法返回false或是抛出异常,整个回调链都会终止执行,撤销事务;

而after_*回调只有抛出异常才能达到相同的效果。

关联回调

回调能在模型关联中使用,甚至可有关联定义。

条件回调

条件通过:if和:unless选项指定,选项的值可以是Symbol、字符串、Proc或数组。

if选项指定什么时候调用回调,unless指定什么时候不调用回调。

使用Symbol时,表示要在调用回调之前执行对应的判断方法。

使用字符串时,但必须是Ruby代码,传入eval方法中执行,

使用Proc,这种形式最适合用在同一行代码能表示的条件上

回调类

有时回调方法可以在其他模型中重用,可以将其封装到类中。

事务回调

还有两个回调会在数据库事务完成时触发:after_commit和after_rollback。

你可能感兴趣的:(Active Record回调)