diff --git a/Gemfile b/Gemfile index 2ce393752..6114ca65d 100644 --- a/Gemfile +++ b/Gemfile @@ -13,7 +13,7 @@ gem 'hanami-router', '~> 0.7', require: false, github: 'hanami/router', gem 'hanami-controller', '~> 0.7', require: false, github: 'hanami/controller', branch: '0.7.x' gem 'hanami-view', '~> 0.7', require: false, github: 'hanami/view', branch: '0.7.x' gem 'hanami-model', '~> 0.7', require: false, github: 'hanami/model', branch: '0.7.x' -gem 'hanami-helpers', '~> 0.5', require: false, github: 'hanami/helpers', branch: 'new-routes-factory' +gem 'hanami-helpers', '~> 0.5', require: false, github: 'hanami/helpers', branch: 'master' gem 'hanami-mailer', '~> 0.3', require: false, github: 'hanami/mailer', branch: '0.3.x' gem 'hanami-assets', '~> 0.4', require: false, github: 'hanami/assets', branch: 'configuration' diff --git a/lib/hanami/middleware.rb b/lib/hanami/middleware.rb index af6d38917..bf8e5d808 100644 --- a/lib/hanami/middleware.rb +++ b/lib/hanami/middleware.rb @@ -67,6 +67,7 @@ def call(env) # @see Hanami::Middleware#prepend def use(middleware, *args, &blk) stack.push [middleware, args, blk] + stack.uniq! end # Prepend a middleware to the stack. @@ -82,6 +83,7 @@ def use(middleware, *args, &blk) # @see Hanami::Middleware#use def prepend(middleware, *args, &blk) stack.unshift [middleware, args, blk] + stack.uniq! end private diff --git a/spec/isolation/middleware/ensure_unique_stack_spec.rb b/spec/isolation/middleware/ensure_unique_stack_spec.rb new file mode 100644 index 000000000..0608cceee --- /dev/null +++ b/spec/isolation/middleware/ensure_unique_stack_spec.rb @@ -0,0 +1,56 @@ +RSpec.describe Hanami::Middleware, type: :cli do + describe "#load!" do + it "loads the middleware stack without duplicates" do + with_project do + generate "action web home#index" + replace "apps/web/application.rb", "Application < Hanami::Application", <<-END +class RackApp + def initialize(app, options = {}, &blk) + @app = app + @options = options + @blk = blk + end + + def call(env) + @app.call(env) + end +end + +class Application < Hanami::Application +END + + replace "apps/web/application.rb", "configure do", <<-END +configure do + block1 = ->() {} + block2 = ->() {} + block3 = ->() {} + + middleware.use Web::RackApp, foo: :bar + middleware.use Web::RackApp, foo: :bar # this is a duplicate and it shouldn't be included + middleware.use Web::RackApp, baz: :bat + middleware.use Web::RackApp, &block1 + middleware.use Web::RackApp, &block1 # this is a duplicate and it shouldn't be included + middleware.use Web::RackApp, &block2 + + middleware.prepend Web::RackApp, foo: :bar # this is a duplicate and it shouldn't be included + middleware.prepend Web::RackApp, cap: :tain + middleware.prepend Web::RackApp, &block1 # this is a duplicate and it shouldn't be included + middleware.prepend Web::RackApp, &block2 # this is a duplicate and it shouldn't be included + middleware.prepend Web::RackApp, &block3 +END + + require Pathname.new(Dir.pwd).join("config", "environment") + Hanami::Components.resolve('all') + + middleware = Web::Application.new.__send__(:middleware) + + # We tried to mount Web::RackApp 11 times. + # + # We have 5 duplicates marked inline. + # + # That leads us to 6 (11 - 5) mounted middleware. + expect(middleware.__send__(:stack).count).to be(6) + end + end + end +end diff --git a/spec/support/fixtures.rb b/spec/support/fixtures.rb index c63f64fe7..23c2eb8a0 100644 --- a/spec/support/fixtures.rb +++ b/spec/support/fixtures.rb @@ -1,6 +1,6 @@ # Please use this app only for: # -# * spec/application_spec.rb +# * spec/unit/application_spec.rb # * spec/isolation/application_configure_spec.rb module UnitTesting class Application < Hanami::Application