Rails Active Record Callbacks 順序
簡易的列出 Ruby on Rails 全部的 active records callbacks 以及執行順序的筆記
開發 Ruby on Rails 中,時常會使用到 callback 的功能,簡單來說可以在 model 的生命週期當中插入自己的程式碼,e.g. 建立完 model 之後呼叫 mailer 去發信、或在驗證之前幫資料消毒等。
隨著專案的規模越來越大,callbacks 越長越多,腦袋冒出一些問題,例如:
- 如果定義順序
A->B
執行的結果會是誰先誰後? - 我該如何找到我全部的 callbacks
執行順序
after_create
的順序會是由上到下,可是換成 after_commit
或是 after_rollback
順序會是相反的
after_create :after_create_one
after_create :after_create_two
after_commit :after_commit_one
after_commit :after_commit_two
def after_create_one
Rails.logger.info '********** after_create_one **********'
end
def after_create_two
Rails.logger.info '********** after_create_two **********'
end
def after_commit_one
Rails.logger.info '********** after_commit_one **********'
end
def after_commit_two
Rails.logger.info '********** after_commit_two **********'
end
我們可以在 console 裡面看到
User._create_callbacks.map(&:filter)
=> [:after_create_two, :after_create_one]
User._commit_callbacks.map(&:filter)
=> [:after_commit_one, :after_commit_two]
Model._*_callbacks.map(&:filter)
Model.__callbacks.each_with_object(Hash.new([])) do |(k, callbacks), result|
next if k == :validate # ignore validations
callbacks.each do |c|
# remove autosaving callbacks from result
next if c.filter.to_s.include?("autosave")
next if c.filter.to_s.include?("_ensure_no_duplicate_errors")
result["#{c.kind}_#{c.name}"] += [c.filter]
end
end
可以幫助我們 debug 快速的找到所有的 callbacks
參考資料
https://effectiva.hr/en/blog/what-active-record-callbacks-are-registered-on-some-model