first pass at the action warden, currently just reproducing basic rack functionality

This commit is contained in:
John Bender 2010-07-23 23:57:02 -07:00
parent f8731c9a8c
commit 2c1da9566c
3 changed files with 39 additions and 26 deletions

View File

@ -112,34 +112,11 @@ module Vagrant
def to_app(env) def to_app(env)
# Prepend the error halt task so errneous environments are halted # Prepend the error halt task so errneous environments are halted
# before the chain even begins. # before the chain even begins.
items = stack.dup.unshift([Env::ErrorHalt, [], nil]) middleware = stack.dup.push([Env::ErrorHalt, [], nil])
# Convert each middleware into a lambda which takes the next # Convert each middleware into a lambda which takes the next
# middleware. # middleware.
items = items.collect do |item| Vagrant::Action::Warden.new(middleware, env)
klass, args, block = item
lambda do |app|
if klass.is_a?(Class)
# A middleware klass which is to be instantiated with the
# app, env, and any arguments given
klass.new(app, env, *args, &block)
elsif klass.respond_to?(:call)
# Make it a lambda which calls the item then forwards
# up the chain
lambda do |e|
klass.call(e)
app.call(e)
end
else
raise "Invalid middleware: #{item.inspect}"
end
end
end
# Append the final step and convert into flattened call chain.
items << lambda { |env| }
items[0...-1].reverse.inject(items.last) { |a,e| e.call(a) }
end end
# Runs the builder stack with the given environment. # Runs the builder stack with the given environment.

View File

@ -0,0 +1,36 @@
module Vagrant
class Action
class Warden
attr_accessor :actions
def initialize(middleware, env)
@stack = []
@actions = middleware.map { |m| finalize_middleware(m, env) }.reverse
end
def call(env)
return if @actions.empty?
@stack.push(@actions.pop).last.call(env)
end
def finalize_middleware(middleware, env)
klass, args, block = middleware
if klass.is_a?(Class)
# A middleware klass which is to be instantiated with the
# app, env, and any arguments given
klass.new(self, env, *args, &block)
elsif klass.respond_to?(:call)
# Make it a lambda which calls the item then forwards
# up the chain
lambda do |e|
klass.call(e)
self.call(e)
end
else
raise "Invalid middleware: #{middleware.inspect}"
end
end
end
end
end

View File

@ -166,7 +166,7 @@ class ActionBuilderTest < Test::Unit::TestCase
middleware.stubs(:is_a?).with(Class).returns(true) middleware.stubs(:is_a?).with(Class).returns(true)
middleware.expects(:new).with(anything, env).returns(result) middleware.expects(:new).with(anything, env).returns(result)
@instance.use middleware @instance.use middleware
result = @instance.to_app(env) result = @instance.to_app(env).actions.first
assert result.kind_of?(Vagrant::Action::Env::ErrorHalt) assert result.kind_of?(Vagrant::Action::Env::ErrorHalt)
end end