123456789_123456789_123456789_123456789_123456789_

Class: ActiveSupport::Callbacks::Callback

Do not use. This class is for internal use only.
Relationships & Source Files
Inherits: Object
Defined in: activesupport/lib/active_support/callbacks.rb

Constant Summary

Class Method Summary

Instance Attribute Summary

Instance Method Summary

Constructor Details

.new(name, filter, kind, options, chain_config) ⇒ Callback

[ GitHub ]

  
# File 'activesupport/lib/active_support/callbacks.rb', line 256

def initialize(name, filter, kind, options, chain_config)
  @chain_config = chain_config
  @name            = name
  @kind            = kind
  @original_filter = filter.object_id
  @filter          = try_shareable_proc(filter)
  @if              = check_conditionals(options[:if])
  @unless          = check_conditionals(options[:unless])

  compiled
end

Class Method Details

.build(chain, filter, kind, options)

[ GitHub ]

  
# File 'activesupport/lib/active_support/callbacks.rb', line 242

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.
    MSG
  end

  new chain.name, filter, kind, options, chain.config
end

Instance Attribute Details

#chain_config (readonly)

[ GitHub ]

  
# File 'activesupport/lib/active_support/callbacks.rb', line 254

attr_reader :chain_config, :filter

#filter (readonly)

[ GitHub ]

  
# File 'activesupport/lib/active_support/callbacks.rb', line 254

attr_reader :chain_config, :filter

#kind (readonly)

[ GitHub ]

  
# File 'activesupport/lib/active_support/callbacks.rb', line 253

attr_reader :kind, :name

#name (readonly)

[ GitHub ]

  
# File 'activesupport/lib/active_support/callbacks.rb', line 253

attr_reader :kind, :name

Instance Method Details

#apply(callback_sequence)

Wraps code with filter

[ GitHub ]

  
# File 'activesupport/lib/active_support/callbacks.rb', line 325

def apply(callback_sequence)
  compiled.apply(callback_sequence)
end

#check_conditionals(conditionals) (private)

[ GitHub ]

  
# File 'activesupport/lib/active_support/callbacks.rb', line 337

def check_conditionals(conditionals)
  return EMPTY_ARRAY if conditionals.blank?

  conditionals = Array(conditionals)
  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.map! { |conditional| try_shareable_proc(conditional) }
end

#compiled

[ GitHub ]

  
# File 'activesupport/lib/active_support/callbacks.rb', line 293

def compiled
  @compiled ||=
    begin
      user_conditions = conditions_lambdas
      user_callback = CallTemplate.build(@filter, self)
      lambda = Ractors.try_shareable_lambda(user_callback, &user_callback.make_lambda)

      case kind
      when :before
        Filters::Before.new(lambda, user_conditions, chain_config, @filter, name)
      when :after
        Filters::After.new(lambda, user_conditions, chain_config)
      when :around
        Filters::Around.new(user_callback, user_conditions)
      end
    end
end

#conditions_lambdas (private)

[ GitHub ]

  
# File 'activesupport/lib/active_support/callbacks.rb', line 352

def conditions_lambdas
  conditions =
    @if.map { |c| CallTemplate.build(c, self).make_lambda } +
    @unless.map { |c| CallTemplate.build(c, self).inverted_lambda }
  conditions.empty? ? EMPTY_ARRAY : conditions.freeze
end

#current_scopes

[ GitHub ]

  
# File 'activesupport/lib/active_support/callbacks.rb', line 329

def current_scopes
  Array(chain_config[:scope]).map { |s| public_send(s) }
end

#duplicates?(other) ⇒ Boolean

[ GitHub ]

  
# File 'activesupport/lib/active_support/callbacks.rb', line 284

def duplicates?(other)
  case @filter
  when Symbol
    matches?(other.kind, other.filter)
  else
    false
  end
end

#freeze

[ GitHub ]

  
# File 'activesupport/lib/active_support/callbacks.rb', line 311

def freeze # :nodoc:
  return self if frozen?

  @filter = Ractors.make_shareable(@filter)
  @if = make_conditionals_ractor_shareable(@if)
  @unless = make_conditionals_ractor_shareable(@unless)
  @compiled = nil

  compiled
  super
  self
end

#make_conditionals_ractor_shareable(conditionals) (private)

[ GitHub ]

  
# File 'activesupport/lib/active_support/callbacks.rb', line 363

def make_conditionals_ractor_shareable(conditionals)
  return conditionals if conditionals.empty?

  Ractors.make_shareable(conditionals)
end

#matches?(_kind, _filter) ⇒ Boolean

[ GitHub ]

  
# File 'activesupport/lib/active_support/callbacks.rb', line 280

def matches?(_kind, _filter)
  @kind == _kind && (filter == _filter || (@original_filter == _filter.object_id))
end

#merge_conditional_options(chain, if_option:, unless_option:)

[ GitHub ]

  
# File 'activesupport/lib/active_support/callbacks.rb', line 268

def merge_conditional_options(chain, if_option:, unless_option:)
  options = {
    if: @if.dup,
    unless: @unless.dup
  }

  options[:if].concat     Array(unless_option)
  options[:unless].concat Array(if_option)

  self.class.build chain, @filter, @kind, options
end

#try_shareable_proc(object) (private)

[ GitHub ]

  
# File 'activesupport/lib/active_support/callbacks.rb', line 359

def try_shareable_proc(object)
  object.is_a?(Proc) ? Ractors.try_shareable_proc(object) : object
end