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

时间:2012-01-11 18:30:37

标签: ruby-on-rails rack middleware rails-3.1

我在Rails 3.1应用程序中使用自定义Rack中间件,它包裹着一个vanilla 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堆栈,只要代码被更​​改,它需要重新加载这个中间件的方法是什么?

3 个答案:

答案 0 :(得分:2)

您想要的工具是autoload。当Rails在dev中重新加载时,它会迭代自动加载并显式定义'unloadable'常量并删除它们(watch stack管理它)。

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

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

我认为应该获得您正在寻找的行为。

请注意,如果您不喜欢自动加载(人们认为它会影响monkeypatch的功能),您可以标记一个常量(unloadable,然后要求文件load(仅使用{ {1}}第二次不会提取文件。  或+ require。这也会在prod中的每个请求中加载类,所以可能有条件地加载或需要取决于env?自动加载可能是IMO的更好选择。

请注意,我发现actual Rails code(不是Rails文档)是最佳参考。

答案 1 :(得分:1)

如果您使用Pow,您可以使用粉末宝石轻松重启Pow,而无需执行touch tmp/restart.txt命令。请参阅https://github.com/Rodreegez/powder

答案 2 :(得分:1)

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

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

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