Gem Version Build Status Coverage Status

Modware

Modware is a library for using middleware (pipeline) patterns in Ruby projects. It features a simple interface and supports "callback" style semantics in the middleware stack, including before, after, and around methods.

Installation

As usual:

gem 'modware'                   # in a Gemfile
spec.add_dependency 'modware'   # in a .gemspec

Usage

Creating a stack

Create a stack using:

stack = Modware::Stack.new(env: klass)

where klass is a Class for the environment instance that will be passed to the layers of the stack. As a shorthand for the common case, you can simply pass an array of keys, e.g.

stack = Modware::Stack.new(env: [:name, :options, :results])

and Modware will define a class that accepts those keys as keyword arguments, and has accessor methods for each (see KeyStruct).

Defining middleware

Middleware is defined as a module that defines one or more middleware methods:

module MyMiddleware

  # define any of these as needed...

  def before(env)
    # code to be called before the base implementation
  end

  def after(env)
    # code to be called after the base implementation
  end

  def around(env)
    # setup/wrapper code
    yield env # continues execution down the stack
    # cleanup code
  end

  def implement(env)
    # completely replaces the base implementation or any earlier middleware's implement()
  end
end

The module may use instance variables and define other methods as needed (e.g. to abide by Metz' rule #2).

To add the middleware to a stack:

stack.add(MyMiddleware)

Middleware is always added to the end of the stack.

Executing a stack

To execute a stack do:

stack.start(*args) { |env|
  # base implementation 
}

The execution sequence of the stack is as follows:

  1. Create environment instance env = env_klass.new(*args)
  2. Call each middleware before(env) method, in the order they were added
  3. Call each middleware around(env) method, in the order they were added. This bottoms out with the last implement(env) method to be added, if any, otherwise the base implementation
  4. Call each middleware after(env) method, in the order they were added
  5. Return env

Helpers

  • Modware.is_middleware?(mod) returns truthy if mod's instance methods include any of the middleware methods :before, :after, :around, or :implement

See also

The middleware gem works well, following a rack-like execution model.

Contributing

Contributions welcome -- feel free to open issues or submit pull requests. Thanks!