1

我们有一个用例,用于在本地开发时安装模拟引擎来处理会话,其中自定义会话中间件在请求通过时通过 Net::http 请求调用模拟引擎。

当有代码更改时,会触发重新加载器,并在此处调用ActiveSupport::Dependencies开始卸载。然后将请求传递给我们的自定义会话中间件并触发 http 请求。 然而,由于 http 请求调用了一个可挂载的引擎,它会再次考虑相同的中间件,并且重新加载器会再次卸载所有依赖项,这会导致第一次重新加载超时。所以目标是能够跳过第二个请求的重新加载。

ActionDispatch::Reloader 我在此处添加了以下代码,它完全符合我的要求。

class Reloader < Executor
  def initialize(app, executor)
    super(app, executor)
  end

  def call(env)
    request = ActionDispatch::Request.new(env)
    return @app.call(env) if skip_request?(request)
    super(env)
  end

  def skip_request?(request)        
    request.path_info.start_with?('/session')
  end
end

然后我想让这个清洁器将其完全拉出到一个模块中,然后从初始化器中进行这样的交换

app.config.middleware.swap(::ActionDispatch::Reloader, MyModule::CustomReloaderMiddleware)

这是模块

require 'action_dispatch'

module MyModule
  class CustomReloaderMiddleware < ActionDispatch::Executor
    def initialize(app, executor)
      @app, @executor = app, executor
    end

    def call(env)
      request = ActionDispatch::Request.new(env)
      return @app.call(env) if skip_request?(request)
      super(env)
    end

    def skip_request?(request)
      request.path_info.start_with?('/session')
    end
  end
end

但我遇到了几个问题。

Uncaught exception: wrong number of arguments (given 1, expected 2)从 for initializein MyModule,当我启动服务器时。然后我尝试了以下

#1

def initialize(app, executor = nil)
  @app, @executor = app, executor
end

#2

def initialize(app, executor = nil)
  @app, @executor = app, ActiveSupport::Reloader
end

他们都正确启动了服务,我看到请求通过这个中间件,但它没有重新加载代码。所以我想知道用自定义重新加载器交换 ActionDispatch::Reloader 的正确方法是什么?

4

1 回答 1

1

您需要将中间件的附加参数传递给swap调用:

app.config.middleware.swap(::ActionDispatch::Reloader, MyModule::CustomReloaderMiddleware, app.reloader)

这与第一次添加ActionDispatch::Reloader时给出的参数相同——它是应用程序的重新加载器,它是 AS::Reloader 的更具体配置的子类(所以你走在正确的轨道上)。

于 2018-08-15T06:18:58.480 回答