例子摘自同事的分享.

总体来说是顺序执行.

当多个过滤器同时使用时, after 过滤器会维护一个栈.

around 会一拆两份, beforeafter.

before 部分顺序执行, 包括 aroundbefore 部分, 遇到 after 就入栈.

action 执行之后, 从栈顶依次弹出 after 来执行.

class HomeController < ApplicationController
  before_action :before1
  around_action :around1
  after_action :after1

  around_action :around2
  before_action :before2
  after_action :after2
  
  before_action :before3
  after_action :after3
  around_action :around3

  def index
    render plain: "Hello World"
  end

  def before1
    puts "before1"
  end

  def before2
    puts "before2"
  end
  
  def before3
    puts "before3"
  end

  def after1
    puts "after1"
  end

  def after2
    puts "after2"
  end
  
  def after3
    puts "after3"
  end

  def around1
    puts "around1 (before)"
    yield
    puts "around1 (after)"
  end

  def around2
    puts "around2 (before)"
    yield
    puts "around2 (after)"
  end
  
  def around3
    puts "around3 (before)"
    yield
    puts "around3 (after)"
  end
  
=begin
before1
around1 (before)
around2 (before)
before2
before3
around3 (before)
around3 (after)
after3
after2
around2 (after)
after1
around1 (after)
=end
end

数据库提交是类似的道理, after_save 直接执行.

after_commit 先入栈, 到了执行步骤就依次出栈执行.

class HomeController < ApplicationController
  def index
    User.create(user_key: 'hello_world', name: 'test')

    render plain: "Hello World"
  end
end

# user.rb

class User < ApplicationRecord
  after_commit :commit_log_1
  after_commit :commit_log_2

  after_save :save_log_1
  after_save :save_log_2

  private

  def save_log_1
    p "save log 1"
  end

  def save_log_2
    p "save log 2"
  end

  def commit_log_1
    p "commit log 1"
  end

  def commit_log_2
    p "commit log 2"
  end
end
=begin
"save log 1"
"save log 2"
"commit log 2"
"commit log 1"
=end