在以下代码中,为什么foo_enabled?
要求EmployeeController.bar
?
class ApplicationController < ActionControlelr::Base
before_action :foo, if: :foo_enabled?
def foo
puts 'foo called'
end
def foo_enabled?
puts 'sleep for 100s !'
true
end
end
class EmployeeController < ApplicationController
skip_before_action :foo, only: [:bar]
def bar
puts 'inside bar'
end
end
答案 0 :(得分:2)
我认为原因是一旦你开始在你的回调上使用条件,那么总是会检查回调以查看它们是否应该运行。
你会非常合理地认为skip_
会从该操作的回调中完全删除该回调。相反,我认为,它增加了一个条件。 only:
条件会添加unless: Proc.new { action_name == 'bar' }
之类的支票。
根据检查条件的顺序,很有可能在foo_enabled?
条件之前检查only:
条件,这就是您看到方法被调用的原因。代码正在迭代回调以检查它们是否应该运行,并且在ApplicationController
中添加的条件之前检查来自EmployeeController
的条件。
相关代码位于activesupport
gem的lib/active_support/callbacks.rb
和actionpack
gem的lib/abstract_controller/callbacks.rb
。这对我来说有点困难,但我认为我所描述的是它的本质。
答案 1 :(得分:1)
foo_enabled?
是应该调用foo
的条件。
然后确定应该调用foo
,但EmployeeController
会跳过它bar
。
如果foo_enabled?
返回false
,则执行时不会执行foo
操作,因此无需“跳过”。
由于before_action
是基于if
的条件,因此必须先评估if
以确定是否应触发该操作。
在做出此确定之后,skip_before_action
将评估是否应跳过它。简化的工作流程说明:
#ApplicationController
if foo_enabled?
#EmployeeController
if skip_action == :foo && !skip_action[:only].includes?(current_action)
foo
end
end