lib/active_support/callbacks.rb in activesupport-6.1.7.10 vs lib/active_support/callbacks.rb in activesupport-7.0.0.alpha1
- old
+ new
@@ -3,10 +3,11 @@
require "active_support/concern"
require "active_support/descendants_tracker"
require "active_support/core_ext/array/extract_options"
require "active_support/core_ext/class/attribute"
require "active_support/core_ext/string/filters"
+require "active_support/core_ext/object/blank"
require "thread"
module ActiveSupport
# Callbacks are code hooks that are run at key points in an object's life cycle.
# The typical use case is to have a base class define a set of callbacks
@@ -274,11 +275,11 @@
end
private_class_method :simple
end
end
- class Callback #:nodoc:#
+ class Callback # :nodoc:#
def self.build(chain, filter, kind, options)
if filter.is_a?(String)
raise ArgumentError, <<-MSG.squish
Passing string to define a callback is not supported. See the `.set_callback`
documentation to see supported values.
@@ -287,25 +288,21 @@
new chain.name, filter, kind, options, chain.config
end
attr_accessor :kind, :name
- attr_reader :chain_config
+ attr_reader :chain_config, :filter
def initialize(name, filter, kind, options, chain_config)
@chain_config = chain_config
@name = name
@kind = kind
@filter = filter
- @key = compute_identifier filter
@if = check_conditionals(options[:if])
@unless = check_conditionals(options[:unless])
end
- def filter; @key; end
- def raw_filter; @filter; end
-
def merge_conditional_options(chain, if_option:, unless_option:)
options = {
if: @if.dup,
unless: @unless.dup
}
@@ -354,30 +351,21 @@
def check_conditionals(conditionals)
return EMPTY_ARRAY if conditionals.blank?
conditionals = Array(conditionals)
- if conditionals.any? { |c| c.is_a?(String) }
+ if conditionals.any?(String)
raise ArgumentError, <<-MSG.squish
Passing string to be evaluated in :if and :unless conditional
options is not supported. Pass a symbol for an instance method,
or a lambda, proc or block, instead.
MSG
end
conditionals.freeze
end
- def compute_identifier(filter)
- case filter
- when ::Proc
- filter.object_id
- else
- filter
- end
- end
-
def conditions_lambdas
@if.map { |c| CallTemplate.build(c, self).make_lambda } +
@unless.map { |c| CallTemplate.build(c, self).inverted_lambda }
end
end
@@ -515,11 +503,11 @@
def invoke_after(arg)
@after.each { |a| a.call(arg) }
end
end
- class CallbackChain #:nodoc:#
+ class CallbackChain # :nodoc:#
include Enumerable
attr_reader :name, :config
def initialize(name, config)
@@ -617,11 +605,11 @@
[type, filters, options.dup]
end
# This is used internally to append, prepend and skip callbacks to the
# CallbackChain.
- def __update_callbacks(name) #:nodoc:
+ def __update_callbacks(name) # :nodoc:
([self] + ActiveSupport::DescendantsTracker.descendants(self)).reverse_each do |target|
chain = target.get_callbacks name
yield target, chain.dup
end
end
@@ -686,14 +674,36 @@
# Skip a previously set callback. Like +set_callback+, <tt>:if</tt> or
# <tt>:unless</tt> options may be passed in order to control when the
# callback is skipped.
#
- # class Writer < Person
- # skip_callback :validate, :before, :check_membership, if: -> { age > 18 }
+ # class Writer < PersonRecord
+ # attr_accessor :age
+ # skip_callback :save, :before, :saving_message, if: -> { age > 18 }
# end
#
+ # When if option returns true, callback is skipped.
+ #
+ # writer = Writer.new
+ # writer.age = 20
+ # writer.save
+ #
+ # Output:
+ # - save
+ # saved
+ #
+ # When if option returns false, callback is NOT skipped.
+ #
+ # young_writer = Writer.new
+ # young_writer.age = 17
+ # young_writer.save
+ #
+ # Output:
+ # saving...
+ # - save
+ # saved
+ #
# An <tt>ArgumentError</tt> will be raised if the callback has not
# already been set (unless the <tt>:raise</tt> option is set to <tt>false</tt>).
def skip_callback(name, *filter_list, &block)
type, filters, options = normalize_callback_params(filter_list, block)
@@ -842,21 +852,15 @@
protected
def get_callbacks(name) # :nodoc:
__callbacks[name.to_sym]
end
- if Module.instance_method(:method_defined?).arity == 1 # Ruby 2.5 and older
- def set_callbacks(name, callbacks) # :nodoc:
- self.__callbacks = __callbacks.merge(name.to_sym => callbacks)
+ def set_callbacks(name, callbacks) # :nodoc:
+ unless singleton_class.method_defined?(:__callbacks, false)
+ self.__callbacks = __callbacks.dup
end
- else # Ruby 2.6 and newer
- def set_callbacks(name, callbacks) # :nodoc:
- unless singleton_class.method_defined?(:__callbacks, false)
- self.__callbacks = __callbacks.dup
- end
- self.__callbacks[name.to_sym] = callbacks
- self.__callbacks
- end
+ self.__callbacks[name.to_sym] = callbacks
+ self.__callbacks
end
end
end
end