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
  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 101
def call(env=nil)
  to_app.call(env)
end
delete(index) click to toggle source

Deletes the given middleware object or index

# File lib/middleware/builder.rb, line 95
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 44
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 68
def insert(index, middleware, *args, &block)
  index = self.index(index) unless index.is_a?(Integer)
  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 76
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 middlware object or index with the new middleware.

# File lib/middleware/builder.rb, line 84
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 55
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 111
def index(object)
  stack.each_with_index do |item, i|
    return i if item[0] == object
  end

  nil
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 123
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 130
def to_app
  @runner_class.new(stack.dup)
end