【问题标题】:Rail 5 swap ActionDispatch::Reloader with a custom reloaderRail 5 使用自定义重新加载器交换 ActionDispatch::Reloader
【发布时间】:2018-08-14 21:12:18
【问题描述】:

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

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

我将以下代码添加到ActionDispatch::Reloader here,它完全符合我的要求。

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) 来自initialize 中的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 的正确方法是什么?

【问题讨论】:

  • 抱歉,最近我的空闲时间有限,再也没有回来深入研究您的问题。这听起来像是一个很好的解决方案。 ??????????
  • 哦,不用担心!你给了我很大的帮助,我从你写的东西中学到了很多!

标签: ruby-on-rails ruby ruby-on-rails-5 ruby-on-rails-5.2 actiondispatch


【解决方案1】:

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

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

这与ActionDispatch::Reloaderfirst added 时给出的参数相同——它是应用程序的重新加载器,它是更具体配置的 AS::Reloader 子类(所以你走对了)。

【讨论】:

  • 这行得通!非常感谢 !!通过这个过程,我学到了很多关于重新加载器的知识。我想这是一个独特的用例,我们从中间件调用模拟引擎,或者你认为重新加载器应该阻止第二次重新加载?
  • 我仍然认为第二次重新加载应该是不必要的——因为第一次应该已经更新了所有内容——在这种情况下,第二次应该被阻止没有被尝试......如果它合理地认为它需要再次重新加载,但是,我不确定它应该做什么:跳过意味着内部请求在已知过时的代码上运行,这可能会非常混乱。 (这里我确定没问题,因为你的虚拟会话处理程序发生变化的可能性似乎微乎其微。)
  • 模拟引擎是我们添加到应用程序中以进行开发的宝石,因此它永远不会动态更改代码。我认为我们在中间件中调用模拟引擎的事实是问题所在。从调试器来看,似乎执行器在重新加载器上调用run!,并在重新加载完成之前将请求传递给下一个中间件。
  • 从中间件对模拟引擎的请求再次从顶部击中中间件,就好像有一个新请求进来,然后卸载所有类并且永远不会将其从中间件中取出并导致第一个请求超时
  • run! 返回时,重新加载完成。 (complete! 是在谈论触发重新加载的请求,而不是重新加载本身。令人困惑的命名?)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多