Module: Toys::Middleware
- Included in:
- Base, StandardMiddleware::AddVerbosityFlags, StandardMiddleware::HandleUsageErrors, StandardMiddleware::SetDefaultDescriptions, StandardMiddleware::ShowHelp, StandardMiddleware::ShowRootVersion
- Defined in:
- lib/toys/middleware.rb
Overview
A middleware is an object that has the opportunity to alter the configuration and runtime behavior of each tool in a Toys CLI. A CLI contains an ordered list of middleware, known as the middleware stack, that together define the CLI's default behavior.
Specifically, a middleware can perform two functions.
First, it can modify the configuration of a tool. After tools are defined from configuration, the middleware stack can make modifications to each tool. A middleware can add flags and arguments to the tool, modify the description, or make any other changes to how the tool is set up.
Second, a middleware can intercept and change tool execution. Like a Rack middleware, a Toys middleware can wrap execution with its own code, replace it outright, or leave it unmodified.
Generally, a middleware is a class that implements the two methods defined
in this module: #config and #run. To
get default implementations that do nothing, a middleware can
include Toys::Middleware or subclass Base, but this
is not required.
Defined Under Namespace
Class Method Summary collapse
-
.resolve_specs(*items) ⇒ Array<Toys::Middleware::Spec>
Resolve all arguments into an array of middleware specs.
-
.spec(middleware, *args, **kwargs, &block) ⇒ Object
Create a middleware spec.
-
.spec_from_array(array) ⇒ Toys::Middleware::Spec
Create a middleware spec from an array specification.
Instance Method Summary collapse
-
#config(tool, loader) ⇒ void
This method is called after a tool has been defined, and gives this middleware the opportunity to modify the tool definition.
-
#run(context) ⇒ void
This method is called when the tool is run.
Class Method Details
.resolve_specs(*items) ⇒ Array<Toys::Middleware::Spec>
Resolve all arguments into an array of middleware specs. Each argument may be one of the following:
- A Toys::Middleware object
- A Spec
- An array whose first element is a middleware name or class, and the subsequent elements are params that define what to pass to the class constructor (see spec_from_array)
171 172 173 174 175 176 177 178 179 180 181 182 |
# File 'lib/toys/middleware.rb', line 171 def resolve_specs(*items) items.map do |item| case item when ::Array spec_from_array(item) when Spec item else spec(item) end end end |
.spec(middleware_object) ⇒ Toys::Middleware::Spec .spec(name, *args, **kwargs, &block) ⇒ Toys::Middleware::Spec
Create a middleware spec.
114 115 116 117 118 119 120 |
# File 'lib/toys/middleware.rb', line 114 def spec(middleware, *args, **kwargs, &block) if middleware.is_a?(::String) || middleware.is_a?(::Symbol) || middleware.is_a?(::Class) Spec.new(nil, middleware, args, kwargs, block) else Spec.new(middleware, nil, nil, nil, nil) end end |
.spec_from_array(array) ⇒ Toys::Middleware::Spec
Create a middleware spec from an array specification.
The array must be 1-4 elements long. The first element must be the middleware name or class. The other three arguments may include any or all of the following optional elements, in any order:
- An array for the positional arguments to pass to the constructor
- A hash for the keyword arguments to pass to the constructor
- A proc for the block to pass to the constructor
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
# File 'lib/toys/middleware.rb', line 135 def spec_from_array(array) middleware = array.first if !middleware.is_a?(::String) && !middleware.is_a?(::Symbol) && !middleware.is_a?(::Class) raise ::ArgumentError, "Bad middleware name: #{middleware.inspect}" end args = [] kwargs = {} block = nil array.slice(1..-1).each do |param| case param when ::Array args += param when ::Hash kwargs = kwargs.merge(param) when ::Proc block = param else raise ::ArgumentError, "Bad param: #{param.inspect}" end end Spec.new(nil, middleware, args, kwargs, block) end |
Instance Method Details
#config(tool, loader) ⇒ void
This method returns an undefined value.
This method is called after a tool has been defined, and gives this
middleware the opportunity to modify the tool definition. It is passed
the tool definition object and the loader, and can make any changes to
the tool definition. In most cases, this method should also call
yield, which passes control to the next middleware in the stack. A
middleware can disable modifications done by subsequent middleware by
omitting the yield call, but this is uncommon.
This basic implementation does nothing and simply yields to the next middleware.
65 66 67 |
# File 'lib/toys/middleware.rb', line 65 def config(tool, loader) # rubocop:disable Lint/UnusedMethodArgument yield end |
#run(context) ⇒ void
This method returns an undefined value.
This method is called when the tool is run. It gives the middleware an
opportunity to modify the runtime behavior of the tool. It is passed
the tool instance (i.e. the object that hosts a tool's run method),
and you can use this object to access the tool's options and other
context data. In most cases, this method should also call yield,
which passes control to the next middleware in the stack. A middleware
can "wrap" normal execution by calling yield somewhere in its
implementation of this method, or it can completely replace the
execution behavior by not calling yield at all.
Like a tool's run method, this method's return value is unused. If
you want to output from a tool, write to stdout or stderr. If you want
to set the exit status code, call Context#exit on the context.
This basic implementation does nothing and simply yields to the next middleware.
90 91 92 |
# File 'lib/toys/middleware.rb', line 90 def run(context) # rubocop:disable Lint/UnusedMethodArgument yield end |