Class: Vagrant::Action::Builder
- Inherits:
-
Object
- Object
- Vagrant::Action::Builder
- Defined in:
- lib/vagrant/action/builder.rb
Overview
Action builder which provides a nice DSL for building up
a middleware sequence for Vagrant actions. This code is based
heavily off of Rack::Builder
and ActionDispatch::MiddlewareStack
in Rack and Rails, respectively.
Usage
Building an action sequence is very easy:
app = Vagrant::Action::Builder.new.tap do |b|
b.use MiddlewareA
b.use MiddlewareB
end
Vagrant::Action.run(app)
Instance Attribute Summary collapse
-
#stack ⇒ Array
readonly
This is the stack of middlewares added.
Class Method Summary collapse
-
.build(middleware, *args, &block) ⇒ Builder
This is a shortcut for a middleware sequence with only one item in it.
Instance Method Summary collapse
-
#call(env) ⇒ Object
Runs the builder stack with the given environment.
-
#delete(index) ⇒ Object
Deletes the given middleware object or index.
-
#flatten ⇒ Object
Returns a mergeable version of the builder.
-
#index(object) ⇒ Integer
Returns the numeric index for the given middleware object.
-
#initialize ⇒ Builder
constructor
A new instance of Builder.
-
#initialize_copy(original) ⇒ Object
Implement a custom copy that copies the stack variable over so that we don't clobber that.
-
#insert(index, middleware, *args, &block) ⇒ Object
(also: #insert_before)
Inserts a middleware at the given index or directly before the given middleware object.
-
#insert_after(index, middleware, *args, &block) ⇒ Object
Inserts a middleware after the given index or middleware object.
-
#replace(index, middleware, *args, &block) ⇒ Object
Replaces the given middlware object or index with the new middleware.
-
#to_app(env) ⇒ Object
Converts the builder stack to a runnable action sequence.
-
#use(middleware, *args, &block) ⇒ Object
Adds a middleware class to the middleware stack.
Constructor Details
#initialize ⇒ Builder
Returns a new instance of Builder.
35 36 37 |
# File 'lib/vagrant/action/builder.rb', line 35 def initialize @stack = [] end |
Instance Attribute Details
#stack ⇒ Array (readonly)
This is the stack of middlewares added. This should NOT be used directly.
24 25 26 |
# File 'lib/vagrant/action/builder.rb', line 24 def stack @stack end |
Class Method Details
.build(middleware, *args, &block) ⇒ Builder
This is a shortcut for a middleware sequence with only one item in it. For a description of the arguments and the documentation, please see #use instead.
31 32 33 |
# File 'lib/vagrant/action/builder.rb', line 31 def self.build(middleware, *args, &block) new.use(middleware, *args, &block) end |
Instance Method Details
#call(env) ⇒ Object
Runs the builder stack with the given environment.
115 116 117 |
# File 'lib/vagrant/action/builder.rb', line 115 def call(env) to_app(env).call(env) end |
#delete(index) ⇒ Object
Deletes the given middleware object or index
109 110 111 112 |
# File 'lib/vagrant/action/builder.rb', line 109 def delete(index) index = self.index(index) unless index.is_a?(Integer) stack.delete_at(index) end |
#flatten ⇒ Object
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.
50 51 52 53 54 |
# File 'lib/vagrant/action/builder.rb', line 50 def flatten lambda do |env| self.call(env) end end |
#index(object) ⇒ Integer
Returns the numeric index for the given middleware object.
123 124 125 126 127 128 129 130 |
# File 'lib/vagrant/action/builder.rb', line 123 def index(object) stack.each_with_index do |item, i| return i if item[0] == object return i if item[0].respond_to?(:name) && item[0].name == object end nil end |
#initialize_copy(original) ⇒ Object
Implement a custom copy that copies the stack variable over so that we don't clobber that.
41 42 43 44 45 |
# File 'lib/vagrant/action/builder.rb', line 41 def initialize_copy(original) super @stack = original.stack.dup end |
#insert(index, middleware, *args, &block) ⇒ Object Also known as: insert_before
Inserts a middleware at the given index or directly before the given middleware object.
74 75 76 77 78 79 80 81 82 83 84 85 |
# File 'lib/vagrant/action/builder.rb', line 74 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 if middleware.kind_of?(Builder) middleware.stack.reverse.each do |stack_item| stack.insert(index, stack_item) end else stack.insert(index, [middleware, args, block]) end end |
#insert_after(index, middleware, *args, &block) ⇒ Object
Inserts a middleware after the given index or middleware object.
90 91 92 93 94 |
# File 'lib/vagrant/action/builder.rb', line 90 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 |
#replace(index, middleware, *args, &block) ⇒ Object
Replaces the given middlware object or index with the new middleware.
98 99 100 101 102 103 104 105 106 |
# File 'lib/vagrant/action/builder.rb', line 98 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 |
#to_app(env) ⇒ Object
Converts the builder stack to a runnable action sequence.
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 |
# File 'lib/vagrant/action/builder.rb', line 136 def to_app(env) app_stack = nil # If we have action hooks, then we apply them if env[:action_hooks] builder = self.dup # These are the options to pass into hook application. = {} # If we already ran through once and did append/prepends, # then don't do it again. if env[:action_hooks_already_ran] [:no_prepend_or_append] = true end # Specify that we already ran, so in the future we don't repeat # the prepend/append hooks. env[:action_hooks_already_ran] = true # Apply all the hooks to the new builder instance env[:action_hooks].each do |hook| hook.apply(builder, ) end # The stack is now the result of the new builder app_stack = builder.stack.dup end # If we don't have a stack then default to using our own app_stack ||= stack.dup # Wrap the middleware stack with the Warden to provide a consistent # and predictable behavior upon exceptions. Warden.new(app_stack, env) end |
#use(middleware, *args, &block) ⇒ Object
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.
61 62 63 64 65 66 67 68 69 70 |
# File 'lib/vagrant/action/builder.rb', line 61 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 |