我在我的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)。这可能对生产毫无帮助。我面前没有类似的代码,所以我无法测试它。