class Hanami::Utils::Callbacks::Chain

Series of callbacks to be executed

@since 0.1.0 @private

Attributes

chain[R]

Public Class Methods

new() click to toggle source

Returns a new chain

@return [Hanami::Utils::Callbacks::Chain]

@since 0.2.0

# File lib/hanami/utils/callbacks.rb, line 25
def initialize
  @chain = Concurrent::Array.new
end

Public Instance Methods

append(*callbacks, &block) click to toggle source

Appends the given callbacks to the end of the chain.

@param callbacks [Array] one or multiple callbacks to append @param block [Proc] an optional block to be appended

@return [void]

@raise [RuntimeError] if the object was previously frozen

@see prepend @see run @see Hanami::Utils::Callbacks::Callback @see Hanami::Utils::Callbacks::MethodCallback @see Hanami::Utils::Callbacks::Chain#freeze

@since 0.3.4

@example

require 'hanami/utils/callbacks'

chain = Hanami::Utils::Callbacks::Chain.new

# Append a Proc to be used as a callback, it will be wrapped by `Callback`
# The optional argument(s) correspond to the one passed when invoked the chain with `run`.
chain.append { Authenticator.authenticate! }
chain.append { |params| ArticleRepository.new.find(params[:id]) }

# Append a Symbol as a reference to a method name that will be used as a callback.
# It will wrapped by `MethodCallback`
# If the #notificate method accepts some argument(s) they should be passed when `run` is invoked.
chain.append :notificate
# File lib/hanami/utils/callbacks.rb, line 60
def append(*callbacks, &block)
  callables(callbacks, block).each do |c|
    @chain.push(c)
  end

  @chain.uniq!
end
dup() click to toggle source

Return a duplicate callbacks chain

@return [Hanami::Utils::Callbacks] the duplicated chain

@since 2.0.0

Calls superclass method
# File lib/hanami/utils/callbacks.rb, line 163
def dup
  super.tap do |instance|
    instance.instance_variable_set(:@chain, instance.chain.dup)
  end
end
freeze() click to toggle source

It freezes the object by preventing further modifications.

@since 0.2.0

@see ruby-doc.org/core/Object.html#method-i-freeze

@example

require 'hanami/utils/callbacks'

chain = Hanami::Utils::Callbacks::Chain.new
chain.freeze

chain.frozen?  # => true

chain.append :authenticate! # => RuntimeError
Calls superclass method
# File lib/hanami/utils/callbacks.rb, line 184
def freeze
  super
  @chain.freeze
end
prepend(*callbacks, &block) click to toggle source

Prepends the given callbacks to the beginning of the chain.

@param callbacks [Array] one or multiple callbacks to add @param block [Proc] an optional block to be added

@return [void]

@raise [RuntimeError] if the object was previously frozen

@see append @see run @see Hanami::Utils::Callbacks::Callback @see Hanami::Utils::Callbacks::MethodCallback @see Hanami::Utils::Callbacks::Chain#freeze

@since 0.3.4

@example

require 'hanami/utils/callbacks'

chain = Hanami::Utils::Callbacks::Chain.new

# Add a Proc to be used as a callback, it will be wrapped by `Callback`
# The optional argument(s) correspond to the one passed when invoked the chain with `run`.
chain.prepend { Authenticator.authenticate! }
chain.prepend { |params| ArticleRepository.new.find(params[:id]) }

# Add a Symbol as a reference to a method name that will be used as a callback.
# It will wrapped by `MethodCallback`
# If the #notificate method accepts some argument(s) they should be passed when `run` is invoked.
chain.prepend :notificate
# File lib/hanami/utils/callbacks.rb, line 99
def prepend(*callbacks, &block)
  callables(callbacks, block).each do |c|
    @chain.unshift(c)
  end

  @chain.uniq!
end
run(context, *args) click to toggle source

Runs all the callbacks in the chain. The only two ways to stop the execution are: ‘raise` or `throw`.

@param context [Object] the context where we want the chain to be invoked. @param args [Array] the arguments that we want to pass to each single callback.

@since 0.1.0

@example

require 'hanami/utils/callbacks'

class Action
  private
  def authenticate!
  end

  def set_article(params)
  end
end

action = Action.new
params = Hash[id: 23]

chain = Hanami::Utils::Callbacks::Chain.new
chain.append :authenticate!, :set_article

chain.run(action, params)

# `params` will only be passed as #set_article argument, because it has an arity greater than zero

chain = Hanami::Utils::Callbacks::Chain.new

chain.append do
  # some authentication logic
end

chain.append do |params|
  # some other logic that requires `params`
end

chain.run(action, params)

Those callbacks will be invoked within the context of `action`.
# File lib/hanami/utils/callbacks.rb, line 152
def run(context, *args)
  @chain.each do |callback|
    callback.call(context, *args)
  end
end

Private Instance Methods

callables(callbacks, block) click to toggle source

@api private

# File lib/hanami/utils/callbacks.rb, line 196
def callables(callbacks, block)
  callbacks.push(block) if block
  callbacks.map { |c| Factory.fabricate(c) }
end