class Middleware::Builder

This provides a DSL for building up a stack of middlewares.

This code is based heavily off of `Rack::Builder` and `ActionDispatch::MiddlewareStack` in Rack and Rails, respectively.

# Usage

Building a middleware stack is very easy:

app = Middleware::Builder.new do
  use A
  use B
end

# Call the middleware
app.call(7)

Public Class Methods

new(opts=nil, &block) click to toggle source

Initializes the builder. An optional block can be passed which will be evaluated in the context of the instance.

Example:

Builder.new do
  use A
  use B
end

@param [Hash] opts Options hash @option opts [Class] :runner_class The class to wrap the middleware stack

in which knows how to run them.

@yield [] Evaluated in this instance which allows you to use methods

like {#use} and such.
# File lib/middleware/builder.rb, line 35
def initialize(opts=nil, &block)
  opts ||= {}
  @runner_class   = opts[:runner_class] || Runner
  @reuse_instance = opts[:reuse_instance]
  instance_eval(&block) if block_given?
end

Public Instance Methods

call(env=nil) click to toggle source

Runs the builder stack with the given environment.

# File lib/middleware/builder.rb, line 103
def call(env=nil)
  if @reuse_instance
    runner_instance.call(env)
  else
    to_app.call(env)
  end
end
delete(index) click to toggle source

Deletes the given middleware object or index

# File lib/middleware/builder.rb, line 97
def delete(index)
  index = self.index(index) unless index.is_a?(Integer)
  stack.delete_at(index)
end
flatten() click to toggle source

Returns a mergeable version of the builder. If `use` is called with the return value of this method, then the stack will merge, instead of being treated as a separate single middleware.

# File lib/middleware/builder.rb, line 45
def flatten
  lambda do |env|
    self.call(env)
  end
end
insert(index, middleware, *args, &block) click to toggle source

Inserts a middleware at the given index or directly before the given middleware object.

# File lib/middleware/builder.rb, line 69
def insert(index, middleware, *args, &block)
  index = self.index(index) unless index.is_a?(Integer)
  raise "no such middleware to insert before: #{index.inspect}" unless index
  stack.insert(index, [middleware, args, block])
end
Also aliased as: insert_before
insert_after(index, middleware, *args, &block) click to toggle source

Inserts a middleware after the given index or middleware object.

# File lib/middleware/builder.rb, line 78
def insert_after(index, middleware, *args, &block)
  index = self.index(index) unless index.is_a?(Integer)
  raise "no such middleware to insert after: #{index.inspect}" unless index
  insert(index + 1, middleware, *args, &block)
end
insert_before(index, middleware, *args, &block)
Alias for: insert
replace(index, middleware, *args, &block) click to toggle source

Replaces the given middleware object or index with the new middleware.

# File lib/middleware/builder.rb, line 86
def replace(index, middleware, *args, &block)
  if index.is_a?(Integer)
    delete(index)
    insert(index, middleware, *args, &block)
  else
    insert_before(index, middleware, *args, &block)
    delete(index)
  end
end
use(middleware, *args, &block) click to toggle source

Adds a middleware class to the middleware stack. Any additional args and a block, if given, are saved and passed to the initializer of the middleware.

@param [Class] middleware The middleware class

# File lib/middleware/builder.rb, line 56
def use(middleware, *args, &block)
  if middleware.kind_of?(Builder)
    # Merge in the other builder's stack into our own
    self.stack.concat(middleware.stack)
  else
    self.stack << [middleware, args, block]
  end

  self
end

Protected Instance Methods

index(object) click to toggle source

Returns the numeric index for the given middleware object.

@param [Object] object The item to find the index for @return [Integer]

# File lib/middleware/builder.rb, line 117
def index(object)
  stack.each_with_index do |item, i|
    return i if item[0] == object
  end

  nil
end
runner_instance() click to toggle source
# File lib/middleware/builder.rb, line 140
def runner_instance
  @runner_instance ||= to_app
end
stack() click to toggle source

Returns the current stack of middlewares. You probably won't need to use this directly, and it's recommended that you don't.

@return [Array]

# File lib/middleware/builder.rb, line 129
def stack
  @stack ||= []
end
to_app() click to toggle source

Converts the builder stack to a runnable action sequence.

@return [Object] A callable object

# File lib/middleware/builder.rb, line 136
def to_app
  @runner_class.new(stack.dup)
end