lib/hanami/slice/routing/middleware/stack.rb in hanami-2.0.0.beta3 vs lib/hanami/slice/routing/middleware/stack.rb in hanami-2.0.0.beta4
- old
+ new
@@ -1,7 +1,10 @@
# frozen_string_literal: true
+require "hanami/middleware"
+require "hanami/errors"
+
module Hanami
class Slice
module Routing
# @since 2.0.0
# @api private
@@ -38,27 +41,34 @@
# @since 2.0.0
# @api private
attr_reader :stack
# @since 2.0.0
+ # @api public
+ attr_reader :namespaces
+
+ # @since 2.0.0
# @api private
def initialize
@prefix = ROOT_PREFIX
@stack = Hash.new { |hash, key| hash[key] = [] }
+ @namespaces = [Hanami::Middleware]
end
# @since 2.0.0
# @api private
def initialize_copy(source)
super
@prefix = source.instance_variable_get(:@prefix).dup
@stack = stack.dup
+ @namespaces = namespaces.dup
end
# @since 2.0.0
# @api private
- def use(middleware, *args, before: nil, after: nil, &blk)
+ def use(spec, *args, before: nil, after: nil, &blk)
+ middleware = resolve_middleware_class(spec)
item = [middleware, args, blk]
if before
@stack[@prefix].insert((idx = index_of(before)).zero? ? 0 : idx - 1, item)
elsif after
@@ -138,9 +148,43 @@
private
# @since 2.0.0
def index_of(middleware)
@stack[@prefix].index { |(m, *)| m.equal?(middleware) }
+ end
+
+ # @since 2.0.0
+ def resolve_middleware_class(spec)
+ case spec
+ when Symbol then load_middleware_class(spec)
+ when Class, Module then spec
+ else
+ if spec.respond_to?(:call)
+ spec
+ else
+ raise UnsupportedMiddlewareSpecError, spec
+ end
+ end
+ end
+
+ # @since 2.0.0
+ def load_middleware_class(spec)
+ begin
+ require "hanami/middleware/#{spec}"
+ rescue LoadError # rubocop:disable Lint/SuppressedException
+ end
+
+ class_name = Hanami::Utils::String.classify(spec.to_s)
+ namespace = namespaces.detect { |ns| ns.const_defined?(class_name) }
+
+ if namespace
+ namespace.const_get(class_name)
+ else
+ raise(
+ UnsupportedMiddlewareSpecError,
+ "Failed to find corresponding middleware class for `#{spec}` in #{namespaces.join(', ')}"
+ )
+ end
end
end
end
end
end