In current realization of Rack::Builder the method :use dictates that
middlewares must be instances of some class by internal invoking :new
initializer.
Thus Rack’s Builder demands to delegate creation of middleware object
and demands existing special class for middleware. Though in most cases
middleware conforms with singleton pattern. Or just simply a callable
object.
Moreover, it is always more cleary to link already existing middleware,
created outside of builder. Is middleware worse than ordinary app in
respect of this?
Unneeded delegation of creation makes unneeded coupling and unneeded
restrictions.
As Vidar H. well wrote in his post “Cohesion vs. coupling”
http://www.hokstad.com/why-coupling-is-always-bad-cohesion-vs-coupling.html
Looking at realization of Builder’s methods we can make something like
this.
first variant
module MiddleHello
this method needs only
to prevent duplicating of code in second example
def self.invoke app, env, who, whom
status, header, resp = app.call env
add_str = “”
if resp.kind_of? Rack::Response
new_resp = Rack::Response.new(add_str, status, header)
new_resp.write resp.body
return new_resp.finish
end
[status, header, (add_str + resp)]
end
def self.creator app
@app = app
self
end
def self.call env
invoke @app, env, self.method(:call), “#{self.class}: #{self}”
end
end
second variant
middle_hello = proc do |app|
proc do |env|
# just for preventing duplication of code
MiddleHello.invoke app, env, Proc, Proc
end
end
builder = Rack::Builder.new do
use …
…
use …
map ‘/some_path’ do
run MiddleHello.method(:creator) # :run instead of :use !
run middle_hello # :run instead of :use !
run OurApp
end
end
It works. Now I can not find better solution without changing of Builder
class.
But it looks like a hack.
First. There are no warranties that realization of Builder’s methods
will not have changed in the future.
Second. It is still needed an additional object for creating a
middleware object.
Third, and maybe more important. This breaks the semantics of Builder’s
language. And it is losing distinction in declarations of middlewares
and ordinary apps.
Of course we can remake the Builder or make a subclass from it. But can
it cause conflicts with hostings where Rack is used for administration?