# frozen_string_literal: truemoduleAbstractController# = Abstract Controller Callbacks## Abstract Controller provides hooks during the life cycle of a controller action.# Callbacks allow you to trigger logic during this cycle. Available callbacks are:## * <tt>after_action</tt># * <tt>append_after_action</tt># * <tt>append_around_action</tt># * <tt>append_before_action</tt># * <tt>around_action</tt># * <tt>before_action</tt># * <tt>prepend_after_action</tt># * <tt>prepend_around_action</tt># * <tt>prepend_before_action</tt># * <tt>skip_after_action</tt># * <tt>skip_around_action</tt># * <tt>skip_before_action</tt>## NOTE: Calling the same callback multiple times will overwrite previous callback definitions.#moduleCallbacksextendActiveSupport::Concern# Uses ActiveSupport::Callbacks as the base functionality. For# more details on the whole callback system, read the documentation# for ActiveSupport::Callbacks.includeActiveSupport::Callbacksincludeddodefine_callbacks:process_action,terminator: ->(controller,result_lambda){result_lambda.call;controller.performed?},skip_after_callbacks_if_terminated: trueend# Override <tt>AbstractController::Base#process_action</tt> to run the# <tt>process_action</tt> callbacks around the normal behavior.defprocess_action(*args)run_callbacks(:process_action)dosuperendendmoduleClassMethods# If +:only+ or +:except+ are used, convert the options into the# +:if+ and +:unless+ options of ActiveSupport::Callbacks.## The basic idea is that <tt>:only => :index</tt> gets converted to# <tt>:if => proc {|c| c.action_name == "index" }</tt>.## Note that <tt>:only</tt> has priority over <tt>:if</tt> in case they# are used together.## only: :index, if: -> { true } # the :if option will be ignored.## Note that <tt>:if</tt> has priority over <tt>:except</tt> in case they# are used together.## except: :index, if: -> { true } # the :except option will be ignored.## ==== Options# * <tt>only</tt> - The callback should be run only for this action.# * <tt>except</tt> - The callback should be run for all actions except this action.def_normalize_callback_options(options)_normalize_callback_option(options,:only,:if)_normalize_callback_option(options,:except,:unless)enddef_normalize_callback_option(options,from,to)# :nodoc:iffrom=options[from]_from=Array(from).map(&:to_s).to_setfrom=proc{|c|_from.include?c.action_name}options[to]=Array(options[to]).unshift(from)endend# Take callback names and an optional callback proc, normalize them,# then call the block with each callback. This allows us to abstract# the normalization across several methods that use it.## ==== Parameters# * <tt>callbacks</tt> - An array of callbacks, with an optional# options hash as the last parameter.# * <tt>block</tt> - A proc that should be added to the callbacks.## ==== Block Parameters# * <tt>name</tt> - The callback to be added.# * <tt>options</tt> - A hash of options to be used when adding the callback.def_insert_callbacks(callbacks,block=nil)options=callbacks.extract_options!_normalize_callback_options(options)callbacks.push(block)ifblockcallbacks.eachdo|callback|yieldcallback,optionsendend### :method: before_action## :call-seq: before_action(names, block)## Append a callback before actions. See _insert_callbacks for parameter details.### :method: prepend_before_action## :call-seq: prepend_before_action(names, block)## Prepend a callback before actions. See _insert_callbacks for parameter details.### :method: skip_before_action## :call-seq: skip_before_action(names)## Skip a callback before actions. See _insert_callbacks for parameter details.### :method: append_before_action## :call-seq: append_before_action(names, block)## Append a callback before actions. See _insert_callbacks for parameter details.### :method: after_action## :call-seq: after_action(names, block)## Append a callback after actions. See _insert_callbacks for parameter details.### :method: prepend_after_action## :call-seq: prepend_after_action(names, block)## Prepend a callback after actions. See _insert_callbacks for parameter details.### :method: skip_after_action## :call-seq: skip_after_action(names)## Skip a callback after actions. See _insert_callbacks for parameter details.### :method: append_after_action## :call-seq: append_after_action(names, block)## Append a callback after actions. See _insert_callbacks for parameter details.### :method: around_action## :call-seq: around_action(names, block)## Append a callback around actions. See _insert_callbacks for parameter details.### :method: prepend_around_action## :call-seq: prepend_around_action(names, block)## Prepend a callback around actions. See _insert_callbacks for parameter details.### :method: skip_around_action## :call-seq: skip_around_action(names)## Skip a callback around actions. See _insert_callbacks for parameter details.### :method: append_around_action## :call-seq: append_around_action(names, block)## Append a callback around actions. See _insert_callbacks for parameter details.# set up before_action, prepend_before_action, skip_before_action, etc.# for each of before, after, and around.[:before,:after,:around].eachdo|callback|define_method"#{callback}_action"do|*names,&blk|_insert_callbacks(names,blk)do|name,options|set_callback(:process_action,callback,name,options)endenddefine_method"prepend_#{callback}_action"do|*names,&blk|_insert_callbacks(names,blk)do|name,options|set_callback(:process_action,callback,name,options.merge(prepend: true))endend# Skip a before, after or around callback. See _insert_callbacks# for details on the allowed parameters.define_method"skip_#{callback}_action"do|*names|_insert_callbacks(names)do|name,options|skip_callback(:process_action,callback,name,options)endend# *_action is the same as append_*_actionalias_method:"append_#{callback}_action",:"#{callback}_action"endendendend