通过自定义中间件为请求重新加载开发中的rails堆栈



我在我的Rails 3.1应用程序中使用了一个定制的Rack中间件,它围绕着一个普通的Rails控制器:

routes.rb

stacked_router = 
  Example::Middleware::StackedRouter.new(ProductsController.action(:show))
match '/:id', :to => stacked_router

example/middleware/stacked_router.rb

class Example::Middleware::StackedRouter
  def initialize(app)
    @app = app
  end
  def call(env)
    # ... do stuff before forwarding the request, then
    @app.call(env) # forward the request
  end
end

这很好用。

然而,有一个问题:当我现在在ProductsController中更改代码时,更改是而不是自动拾取的。我必须手动重新启动应用程序(touch tmp/restart.txt

有什么方法可以告诉Rails堆栈,每当代码发生更改时,它都需要重新加载这段中间件?

您想要的工具是自动加载。当Rails在dev中重新加载时,它会遍历自动加载和显式定义的"unloadable"常量,并删除它们(监视堆栈对此进行管理)。

在插件的主lib目录中,例如lib/stacked_router.rb,如果您声明:

autoload Example::Middleware::StackedRouter, 'lib/middleware/stacked_router'

我认为你应该得到你想要的行为。

请注意,如果您不喜欢自动加载(人们认为这会干扰猴痘的功能),您可以标记一个常量(不可加载,然后要求使用load的文件(仅使用require不会第二次拾取文件)。或+load。这也会在prod中的每个请求中加载类,所以可能会根据env有条件地加载或要求?自动加载可能是更好的选择IMO.

请注意,我发现实际的Rails代码(而不是Rails文档)是最好的参考。

如果您正在使用Pow,您可以使用粉末宝石轻松重新启动Pow,而无需执行触摸tmp/restart.txt命令。看见https://github.com/Rodreegez/powder.

看起来Rails正在将服务器启动时的ProductsController副本加载到中间件中,并保留缓存的副本。我不能100%确定这一点,但当您尝试用proc加载中间件时会发生什么?例如

stacked_router = Proc.new {
  Example::Middleware::StackedRouter.new(ProductsController.action(:show))
}

这将有望使它在每个请求上加载一个新的中间件(和一个新ProductsController)。这可能对生产毫无帮助。我面前没有类似的代码,所以我无法测试它。

最新更新