module Pakyow::Support::Pipeline

Provides pipeline behavior. Pipeline objects can define actions to be called in order on an instance of the pipelined object. Each action can act on the object passed to it. Any action can halt the pipeline, causing the result to be immediately returned without calling other actions. Objects passed through the pipeline should include {Pipeline::Object}.

See {Pakyow::Application} and {Pakyow::Routing::Controller} for more examples.

@example

class Application
  include Pakyow::Support::Pipeline

  action :foo
  action :bar

  def foo(result)
    result << "foo"
  end

  def bar(result)
    result << "bar"
  end
end

class Result
  include Pakyow::Support::Pipeline::Object

  attr_reader :results

  def initialize
    @results = []
  end

  def <<(result)
    @results << result
  end
end

Application.new.call(Result.new).results
=> ["foo", "bar"]

Modules

Pipeline actions can be defined in a module and included in a pipelined object.

@example

module VerifyRequest
  extend Pakyow::Support::Pipeline

  action :verify_request

  def verify_request
    ...
  end
end

class Application
  include Pakyow::Support::Pipeline

  use_pipeline VerifyRequest

  ...
end

Public Class Methods

extended(base) click to toggle source

@api private

# File lib/pakyow/support/pipeline.rb, line 72
def self.extended(base)
  base.extend ClassMethods
  base.extend ClassState unless base.ancestors.include?(ClassState)
  base.class_state :__pipelines, default: {}, inheritable: true
  base.class_state :__pipeline, inheritable: true

  base.instance_variable_set(:@__pipeline, Internal.new)
end
included(base) click to toggle source

@api private

# File lib/pakyow/support/pipeline.rb, line 82
def self.included(base)
  base.extend ClassMethods
  base.extend ClassState unless base.ancestors.include?(ClassState)
  base.prepend Initializer
  base.class_state :__pipelines, default: {}, inheritable: true
  base.class_state :__pipeline, inheritable: true

  # Define a default pipeline so that actions can be defined immediately without ceremony.
  #
  base.pipeline :default do; end
  base.use_pipeline :default
end

Public Instance Methods

call(state) click to toggle source

Calls the pipeline, passing state.

# File lib/pakyow/support/pipeline.rb, line 97
def call(state)
  @__pipeline.call(state)
end
initialize_copy(_) click to toggle source
Calls superclass method
# File lib/pakyow/support/pipeline.rb, line 101
def initialize_copy(_)
  super

  @__pipeline = @__pipeline.dup

  # rebind any methods to the new instance
  @__pipeline.instance_variable_get(:@stack).map! { |action|
    if action.is_a?(::Method) && action.receiver.is_a?(self.class)
      action.unbind.bind(self)
    else
      action
    end
  }
end