Class: Junkfood::Rack::ChainedRouter

Inherits:
Object
  • Object
show all
Defined in:
lib/junkfood/rack/chained_router.rb

Overview

A Rack Application and Middleware that will execute a list of callables in order until it receives a response without the 'X-Cascade' header value set to 'pass'. ChainedRouter will then return the response of said execution. The response of the last callable will be returned if it is executed even if it has the 'X-Cascade' header set. As Middleware, the given app will be the last callable in the chain.

Example as Middleware:

use Junkfood::Rack::ChainedRouter do |router|
  router.add_route Proc.new { |env|
    # This proc is called, but it returns a pass.
    [404, { 'X-Cascade' => 'pass' }, []]
  }
  router.add_route Proc.new { |env|
    # This proc is called, but it also returns a pass.
    [404, { 'X-Cascade' => 'pass' }, []]
  }
end
run Proc.new { |env|
  # The main app is the last callable in ChainRouter's list.
  # And this will be executed.
  [200, { 'Content-Type' => 'text/plain' }, ['Hello World']]
}

Example as Middleware, without block parameter:

use Junkfood::Rack::ChainedRouter do
  add_route Proc.new { |env|
    # This proc is called, but it returns a pass.
    [404, { 'X-Cascade' => 'pass' }, []]
  }
  add_route Proc.new { |env|
    # This proc is called, but it also returns a pass.
    [404, { 'X-Cascade' => 'pass' }, []]
  }
end
run Proc.new { |env|
  # The main app is the last callable in ChainRouter's list.
  # And this will be executed.
  [200, { 'Content-Type' => 'text/plain' }, ['Hello World']]
}

Example as Application:

run Junkfood::Rack::ChainedRouter.new do |router|
  router.add_route Proc.new { |env|
    # This proc is called, but it returns a pass.
    [404, { 'X-Cascade' => 'pass' }, []]
  }
  router.add_route Proc.new { |env|
    # This is the last app to run.
    [200, { 'Content-Type' => 'text/plain' }, ['Hello World']]
  }
  router.add_route Proc.new { |env|
    # So this proc is never called.
    [200, { 'Content-Type' => 'text/plain' }, ['Never Run']]
  }
end

Constant Summary

Instance Method Summary (collapse)

Constructor Details

- (ChainedRouter) initialize(app = nil) {|router| ... }

Returns a new instance of ChainedRouter

Yields:

  • (router)

    block to configure the ChainedRouter if block arity greater than 0.

Yield Parameters:

  • router

    newly instantiated ChainedRouter



104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/junkfood/rack/chained_router.rb', line 104

def initialize(app=nil, &block)
  @chain = []
  if block_given?
    if block.arity == 0
      instance_eval &block
    else
      yield self
    end
  end
  @chain << app if app.respond_to? :call

  # Just validate the arguments
  @chain.each do |link|
    raise ArgumentError unless link.respond_to? :call
  end
end

Instance Method Details

- (Object) add_route(app)

Appends a callable to the end of the call chain.



148
149
150
# File 'lib/junkfood/rack/chained_router.rb', line 148

def add_route(app)
  @chain << app
end

- (Object) call(env)



124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# File 'lib/junkfood/rack/chained_router.rb', line 124

def call(env)
  # Set some defaults if the route set is empty.
  results = [
    HTTP_NOT_FOUND,
    {
      X_CASCADE => PASS,
      CONTENT_TYPE => 'text/plain'
    },
    []]
  # Call each link in chain.
  for link in @chain
    results = link.call env
    return results unless results[1][X_CASCADE] == PASS
  end
  # Return the results of the last link in chain, or the originally
  # set results if chain is empty.
  return results
end