class Symbiont::Trigger

A class that controls the logic of closure execution in the context of other objects. Responsible for dispatching the methods which should be executed in a certain context. Delegation variations depends on the order of contexts.

Trigger supports 3 contexts:

If no context is able to respond to the required method - ContextNoMethodError exception is raised (ContextNoMethodError inherits from NoMethodError).

@api private @since 0.1.0

Constants

ContextNoMethodError

Is raised when no one is able to respond to the required method.

@see #actual_context

@api public @since 0.1.0

IKO

Indicates the direction of context method resolving algorithm. Direction: initial contexts => kernel context => outer context.

@return [Array<Symbol>]

@api public @since 0.1.0

IOK

Indicates the direction of context method resolving algorithm. Direction: initial context => outer context => kernel context.

@return [Array<Symbol>]

@api public @since 0.1.0

IncompatibleContextDirectionError

Is raised when chosen direction (context_direction instance attribute) is not supported by a trigger. Supports only: OIK, OKI, IOK, IKO, KOI, KIO.

@api public @since 0.1.0

KIO

Indicates the direction of context method resolving algorithm. Direction: kernel context => initial contexts => outer context.

@return [Array<Symbol>]

api public @since 0.1.0

KOI

Indicates the direction of context method resolving algorithm. Direction: kernel context => outer context => initial contexts.

@return [Array<Symbol>]

@api public @since 0.1.0

OIK

Indicates the direction of context method resolving algorithm. Direction: outer context => initial contexts => kernel context.

@return [Array<Symbol>]

@api public @since 0.1.0

OKI

Indicates the direction of context method resolving algorithm. Direction: outer context => kernel context => initial contexts.

@return [Array<Symbol>]

@api public @since 0.1.0

UnprovidedClosureAttributeError

Is raised when closure isnt passed.

@api public @since 0.2.0

Attributes

__closure__[R]

Returns proc object that will be triggered in many contexts: initial, outer and kernel.

@return [Proc]

@api private @since 0.1.0

__context_direction__[R]

Returns an array of symbols that represents the direction of contexts. that represents an access method to each of them.

@return [Array<Symbol>]

@api private @since 0.1.0

__inner_contexts__[R]

Returns a set of objects that should be used as the main context series for context method resolving algorithm. The order of object selection depends on their order in a set.

@return [Array<Object>]

@since 0.1.0

__kernel_context__[R]

Returns Kernel object that will be used as Kernel context for context method resolving algorithm.

@return [::Kernel]

@api private @since 0.1.0

__outer_context__[R]

Returns a binding object of corresponding closure (see __closure__). Used as an outer context for context method resolving algorithm.

@return [Object]

@api private @since 0.1.0

Public Class Methods

new(*initial_contexts, context_direction: IOK, &closure) click to toggle source

Instantiates trigger object with corresponding initial contexts, closure and context resolving direction.

@param initial_contexts [Array<Object>]

A set of main context objects which should be used for instance_eval on.
An order of object selection depends on oredr which they are passed.

@param closure [Proc]

closure that will be executed in a set of contexts (initial => outer => kernel by default).
An actual context (#__actual_context__) will be passed to a closure as an attribute.

@raise UnprovidedClosureAttributeError

Raises when closure attribte isnt passed.

@raise IncompatibleContextDirectionError

Is raised when chosen direction is not supported by a trigger.
Supports only OIK, OKI, IOK, IKO, KOI, KIO (see corresponding constant value above).

@api private @since 0.1.0

# File lib/symbiont/trigger.rb, line 155
def initialize(*initial_contexts, context_direction: IOK, &closure)
  # :nocov:
  unless ::Kernel.block_given?
    ::Kernel.raise(UnprovidedClosureAttributeError, 'block attribute should be provided')
  end
  # :nocov:

  # rubocop:disable Layout/SpaceAroundKeyword
  unless(context_direction == IOK || context_direction == OIK || context_direction == OKI ||
         context_direction == IKO || context_direction == KOI || context_direction == KIO)
    ::Kernel.raise(
      IncompatibleContextDirectionError,
      'Incompatible context direction attribute. ' \
      'You should use one of this: OIK, OKI, IOK, IKO, KOI, KIO.'
    )
  end
  # rubocop:enable Layout/SpaceAroundKeyword

  @__closure__           = closure
  @__context_direction__ = context_direction
  @__inner_contexts__    = initial_contexts
  @__outer_context__     = ::Kernel.eval('self', closure.binding)
  @__kernel_context__    = ::Kernel
end

Public Instance Methods

__actual_context__(method_name) click to toggle source

Returns the first context that is able to respond to the required method. The context is chosen in the context direction order (see #context_direction). Raises NoMethodError excepition when no one of the contexts are able to respond to the required method. Basicaly, abstract implementation raises NoMethodError.

@param method_name [Symbol,String] Method that a context should respond to. @raise ContextNoMethodError

@see #context_direction

@api private @since 0.1.0

# File lib/symbiont/trigger.rb, line 218
def __actual_context__(method_name)
  ::Kernel.raise ContextNoMethodError, "No one is able to respond to #{method_name}"
end
__directed_contexts__() click to toggle source

Returns a collection of the all contexts sorted by chosen direction. Represents ordered single-dimentional array of objects (contexts).

@return [Array<Object>]

@see #context_direction

@api private @since 0.1.0

# File lib/symbiont/trigger.rb, line 201
def __directed_contexts__
  __context_direction__.map { |direction| __send__(direction) }.flatten
end
__evaluate__() click to toggle source

Triggers a closure in multiple contexts.

@return void

@see method_missing

@api private @since 0.1.0

# File lib/symbiont/trigger.rb, line 188
def __evaluate__
  instance_eval(&__closure__)
end
__extract_singleton_class__(object) click to toggle source

Returns an internal singleton object of the passed object.

@param object [Any] Extractable object @return [Class] Singleton class of the passed object

@api private @sionce 0.5.0

# File lib/symbiont/trigger.rb, line 283
def __extract_singleton_class__(object)
  # NOTE: `<<` approach is used cuz BasicObject does not support #singleton_class method.
  class << object; self; end
end
method(method_name) click to toggle source

Should return a corresponding method object of the actual context.

@param method_name [String,Symbol] Method name @raise ContextNoMethodError

Is raised when no one of the contexts able to respond to the required method.

@return [Method]

@see method_missing @see respond_to_missing? @see #actual_context

@see [Symbiont::PrivateTrigget#method] @see [Symbiont::PublicTrigger#method]

@api private @since 0.1.0

# File lib/symbiont/trigger.rb, line 274
def method(method_name); end
method_missing(method_name, *arguments, **options, &block) click to toggle source

Delegates method invocation to the corresponding actual context.

@param method_name [String,Symbol] Method name @param arguments [Mixed] Method arguments @param block [Proc] Block @raise ContextNoMethodError

Is rased when no one of the contexts are able to respond tothe required method.

@return void

@see #actual_context

@api private @since 0.1.0

# File lib/symbiont/trigger.rb, line 235
def method_missing(method_name, *arguments, **options, &block)
  __actual_context__(method_name).__send__(method_name, *arguments, **options, &block)
end
respond_to_missing?(method_name, _include_private = false) click to toggle source

Checks that the actual context is able to respond to a required method.

@param method_name [String,Symbol] Method name @param _include_private [Boolean] Include private methods @raise NoMethodError

Is raised when no one of the contexts are able to respond to the required method.

@return [Boolean] Is the actual context able to respond to the required method.

@see method_missing @see #actual_context

@api private @since 0.1.0 :nocov:

# File lib/symbiont/trigger.rb, line 253
def respond_to_missing?(method_name, _include_private = false)
  !!__actual_context__(method_name)
end