文章目录
1.回调是什么?
- 回调是在对象生命周期的某些时刻被调用的方法。
- 通过回调,我们可以编写在创建、保存、更新、删除、验证或从数据库中加载 Active Record 对象时执行的代码。
2.可用的回调
2.1.创建对象
before_validation
after_validation
before_save
around_save
before_create
around_create
after_create
after_save
after_commit/after_rollback
2.2 更新对象
before_validation
after_validation
before_save
around_save
before_update
around_update
after_update
after_save
after_commit/after_rollback
2.3 删除对象
before_destroy
around_destroy
after_destroy
after_commit/after_rollback
2.4 事务回调
after_commit 和 after_rollback 这两个回调会在数据库事务完成时触发
由于只在执行创建、更新或删除动作时触发 after_commit 回调是很常见的,这些操作都拥有别名:
after_create_commit
after_update_commit
after_destroy_commit
2.5.其他情况的回调
after_initialize :当 Active Record 对象被实例化时,不管是通过直接使用 new 方法还是从数据库加载记录,都会调用 after_initialize 回调
after_find :当 Active Record 从数据库中加载记录时,会调用 after_find 回调。
如果同时定义了 after_initialize 和 after_find 回调,会先调用 after_find 回调。
after_touch:当我们在 Active Record 对象上调用 touch 方法时,会调用 after_touch 回调。
3触发回调的方法
create
create!
decrement!
destroy
destroy!
destroy_all
increment!
save
save!
save(validate: false)
toggle!
update_attribute
update
update!
valid?
此外,下面这些查找方法会触发 after_find 回调:
all
first
find
find_by
find_by_*
find_by_*!
find_by_sql
last
每次初始化类的新对象时都会触发 after_initialize 回调。
4 跳过回调的方法
decrement
decrement_counter
delete
delete_all
increment
increment_counter
toggle
touch
update_column
update_columns
update_all
update_counters
5. 关联回调
回调不仅可以在模型关联中使用,还可以通过模型关联定义
after_destroy 回调
假设有一个用户在博客中发表了多篇文章,现在我们要删除这个用户,那么这个用户的所有文章也应该删除
class Article < ApplicationRecord
after_destroy :log_destroy_action
def log_destroy_action
puts 'Article destroyed'
end
end
6.条件回调
在满足指定条件时再调用回调方法。为此,我们可以使用 :if 和 :unless 选项,选项的值可以是符号、Proc 或数组。
6.1 使用符号作为 :if 和 :unless 选项的值
before_save :normalize_card_number, if: :paid_with_card?
6.2 使用 Proc 作为 :if 和 :unless 选项的值
before_save :normalize_card_number, if: Proc.new { |order| order.paid_with_card? }
6.3 在条件回调中使用多个条件
我们可以在同一个回调声明中混合使用 :if 和 :unless 选项:
after_create :send_email_to_author, if: :author_wants_emails?,
unless: Proc.new { |comment| comment.article.ignore_comments?
7 回调类
有时需要在其他模型中重用已有的回调方法,为了解决这个问题,Active Record 允许我们用类来封装回调方法。我们可以根据需要在回调类中声明任意多个回调。