Filters class Callback #:nodoc:# class CallTemplate # :nodoc: class CallbackSequence # :nodoc: class CallbackChain #:nodoc:# module ClassMethods DBMMCBDLTSCcSBJMTSBJMT IUUQTHJUIVCDPNSBJMTSBJMTCMPCDBBDUJWFTVQQPSUMJCBDUJWF@TVQQPSUDBMMCBDLTSC
class CallTemplate class CallbackSequence class CallbackChain module ClassMethods DBMMCBDLTSCcSBJMTSBJMT IUUQTHJUIVCDPNSBJMTSBJMTCMPCDBBDUJWFTVQQPSUMJCBDUJWF@TVQQPSUDBMMCBDLTSC def define_callbacks(*names) options = names.extract_options! names.each do |name| name = name.to_sym set_callbacks name, CallbackChain.new(name, options) module_eval <<-RUBY, __FILE__, __LINE__ + 1 def _run_#{name}_callbacks(&block) run_callbacks #{name.inspect}, &block end def self._#{name}_callbacks get_callbacks(#{name.inspect}) end def self._#{name}_callbacks=(value) set_callbacks(#{name.inspect}, value) end def _#{name}_callbacks __callbacks[#{name.inspect}] end RUBY end end ClassMethods
Filters class Callback class CallTemplate class CallbackSequence class CallbackChain module ClassMethods class CallbackChain #:nodoc:# include Enumerable # ... def initialize(name, config) @name = name @config = { scope: [:kind], terminator: default_terminator }.merge!(config) @chain = [] @callbacks = nil @mutex = Mutex.new end # ... end # An Array with a compile method. CallbackΠϯελϯε͕ೖΔ ྻϥΠΫͳΫϥε
name = name.to_sym set_callbacks name, CallbackChain.new(name, options) module_eval <<-RUBY, __FILE__, __LINE__ + 1 def _run_#{name}_callbacks(&block) run_callbacks #{name.inspect}, &block end def self._#{name}_callbacks get_callbacks(#{name.inspect}) end def self._#{name}_callbacks=(value) set_callbacks(#{name.inspect}, value) end def _#{name}_callbacks __callbacks[#{name.inspect}] end RUBY end end module ActiveSupport module Callbacks module Conditionals module Filters class Callback class CallTemplate class CallbackSequence class CallbackChain module ClassMethods ClassMethods
=> callbacks) end module ActiveSupport module Callbacks module Conditionals module Filters class Callback class CallTemplate class CallbackSequence class CallbackChain module ClassMethods ClassMethods
:around].each do |callback| define_method "#{callback}_action" do |*names, &blk| _insert_callbacks(names, blk) do |name, options| set_callback(:process_action, callback, name, options) end end # ... end end end end AbstractController
= callbacks.compile invoke_sequence = Proc.new do # ... end # Common case: no 'around' callbacks defined if next_sequence.final? # ... else invoke_sequence.call end # ... end module ActiveSupport module Callbacks module Conditionals module Filters class Callback class CallTemplate class CallbackSequence class CallbackChain module ClassMethods Callbacks
|| @mutex.synchronize do final_sequence = CallbackSequence.new @callbacks ||= @chain.reverse.inject(final_sequence) do |callback_sequence, callback| callback.apply callback_sequence end end end # ... end # An Array with a compile method. module ActiveSupport module Callbacks module Conditionals module Filters class Callback class CallTemplate class CallbackSequence class CallbackChain module ClassMethods CallbackChain CallbackΠϯελϯε͕ೖΔྻΛ ࣋ͭΫϥε
|| @mutex.synchronize do final_sequence = CallbackSequence.new @callbacks ||= @chain.reverse.inject(final_sequence) do |callback_sequence, callback| callback.apply callback_sequence end end end # ... end # An Array with a compile method. module ActiveSupport module Callbacks module Conditionals module Filters class Callback class CallTemplate class CallbackSequence class CallbackChain module ClassMethods CallbackChain CallbackΠϯελϯε͕ೖΔྻΛ ࣋ͭΫϥε
self) case kind when :before Filters::Before.build( callback_sequence, user_callback.make_lambda, user_conditions, chain_config, @filter ) when :after Filters::After.build( # before ͱಉ ) when :around callback_sequence.around( user_callback, user_conditions ) end end module ActiveSupport module Callbacks module Conditionals module Filters class Callback class CallTemplate class CallbackSequence class CallbackChain module ClassMethods Callback ίʔϧόοΫຊମ
callback) case filter when Symbol new(nil, filter, [], nil) when String new( nil, :instance_exec, [:value], compile_lambda(filter) ) # ... end end # ... end module ActiveSupport module Callbacks module Conditionals module Filters class Callback class CallTemplate class CallbackSequence class CallbackChain module ClassMethods CallTemplate ίʔϧόοΫΛ࣮ߦ͢Δ ProcΛ࡞ΔΫϥε
self) case kind when :before Filters::Before.build( callback_sequence, user_callback.make_lambda, user_conditions, chain_config, @filter ) when :after Filters::After.build( # before ͱಉ ) when :around callback_sequence.around( user_callback, user_conditions ) end end module ActiveSupport module Callbacks module Conditionals module Filters class Callback class CallTemplate class CallbackSequence class CallbackChain module ClassMethods Callback ίʔϧόοΫຊମ
do |env| target = env.target value = env.value halted = env.halted unless halted result_lambda = -> { user_callback.call target, value } env.halted = halted_lambda.call(target, result_lambda) if env.halted target.send :halted_callback_hook, filter end end env end end module ActiveSupport module Callbacks module Conditionals module Filters class Callback class CallTemplate class CallbackSequence class CallbackChain module ClassMethods Filters if, unlessΛνΣοΫ͠ඞཁͳΒ ίʔϧόοΫΛhalt͢ΔΫϥε
|arg| case arg when :value; value when :target; target when :block; block || raise(ArgumentError) end } result.unshift @method_name result.unshift @override_block || block result.unshift @override_target || target # target, block, method, *arguments = result # target.send(method, *arguments, &block) result end ϦΫΤετΛड͚ͨίϯτϩʔϥ before_actionͰొͨ͠ Πϯελϯεϝιου module ActiveSupport module Callbacks module Conditionals module Filters class Callback class CallTemplate class CallbackSequence class CallbackChain module ClassMethods CallTemplate ίʔϧόοΫΛ࣮ߦ͢Δ ProcΛ࡞ΔΫϥε AwesomeController.new.send(:login_required) ͱҰॹʂʂ
raw_filters.group_by(&:kind).each do |kind, filter| filters[kind] = filter.map(&:raw_filter).map do |f| Filter.new(f, method: f.is_a?(Symbol) ? controller.method(f) : f) end end # ... end def print (@before + @around).map(&:to_a).each do |filter| ActionTracer.logger.info filter end # ... end end
{ |arg| case arg when :value; value when :target; target when :block; block || raise(ArgumentError) end } result.unshift @method_name result.unshift @override_block || block result.unshift @override_target || target # target, block, method, *arguments = result # target.send(method, *arguments, &block) result end expand ͕ݺΕΔͷ ࣮ࡍʹ࣮ߦ͞ΕΔίʔϧόοΫ͚ͩ
NOTE: ActiveSupport::Callbacks::CallTemplate is a private class if tp.method_id == :expand && tp.defined_class == ActiveSupport::Callbacks::CallTemplate if tp.return_value&.first.is_a? ActionController::Base case tp.return_value[2] # ... when Symbol # filter is a method applied_filters << tp.return_value[2] end end end end end def self.applied_filters @applied_filters ||= [] end end BDUJPO@USBDFSSCcNBLJDBNFMBDUJPO@USBDFS IUUQTHJUIVCDPNNBLJDBNFMBDUJPO@USBDFSCMPCGMJCBDUJPO@USBDFSBDUJPO@USBDFSSC