ActionController :: Base.relative_url_root的替代品是什么?

我正在将2.x rails应用程序移植到rails3; 我们称之为foo-app。 Foo-app是更大的rails应用程序的一部分,位于main_rails_app.com/foo-app。 以前我们只是在foo-app生产配置中设置以下内容,以确保我们的foo-app路由正常工作:

ActionController::Base.relative_url_root = "/foo-app" 

但是,使用rails3,我现在得到:

 DEPRECATION WARNING: ActionController::Base.relative_url_root is ineffective. Please stop using it. 

我已经将配置条目更改为以下内容:

 config.action_controller.relative_url_root = "/foo-app" 

这主要是因为所有对外部资源(javascript / css / images)的调用都将使用/ foo-app。 但是,我的路线没有任何改变,换句话说,foo-app root_path给我’/’当我期待’/ foo-app’。

两个问题:

  1. 什么是ActionController :: Base.relative_url_root的替代品
  2. 如果是config.action_controller.relative_url_root,那么为什么我的路由没有反映我设置的relative_url_root值?

您应该能够处理routes.rb文件中的所有内容。 将所有当前路线包裹在范围内; 例如。

 scope "/context_root" do resources :controller resources :another_controller match 'welcome/', :to => "welcome#index" root :to => "welcome#index" end 

然后,您可以通过rake routesvalidation您的路由,他们应该相应地显示您的路由,包括您的上下文根(relative_url_root)

如果您通过Passenger进行部署,请使用RackBaseURI指令: http : //www.modrails.com/documentation/Users%20guide%20Apache.html#RackBaseURI

否则,您可以使用以下块将config.ru语句包装在config.ru

 map ActionController::Base.config.relative_url_root || "/" do run FooApp::Application end 

然后,您只需将环境变量RAILS_RELATIVE_URL_ROOT设置为“/ foo-app”。 这甚至适用于在gem或插件中设置的路线。

警告:不要混用这两种解决方案。

我觉得我必须过度复杂化和/或遗漏一些东西,但这个问题让我感到沮丧一段时间了,这是我的笔记。

摘要

有两个单独的问题,每个问题有两个点用于动态和静态路由:

  1. 如何使路由正确匹配传入的URL
    • 用于路线
    • 对于静态文件
  2. 如何生成包含relative_root的URL
    • 通过url助手
    • 对于静态资产

解决所有四点的一种方法:

  • 配置Nginx以剥离relative_root部分
    • 这解决了路线匹配问题; 只需编写期望URL处于/喜欢开发的路由
    • 静态文件也在开发中提供
  • 设置RAILS_RELATIVE_URL_ROOT环境变量
    • 这解决了生成的静态资产助手
  • 使用下面的ScriptName中间件(修改它以使用环境中的值)
    • 这解决了生成的url助手,例如users_path

在config.ru中将Rails应用程序包装在Rack :: URLMap中(Christoph的回答)

 # config.ru map '/relative_root' do run Myapp::Application end 
  • 要求传入的URL包含relative_url_root(Nginx可以配置为删除或保留此;请参阅下文)
  • Rack将relative_url_root附加到Rack env SCRIPT_NAME rack / urlmap.rb:62
  • Rails将当前请求的SCRIPT_NAME到url_for options metal / url_for.rb:41
  • Rails’url_for在生成路径routing / url_for.rb:133时预先设置脚本名称

因此,它涵盖了由url帮助程序生成的URL,例如,给定UserControllerusers_path将以相对url根为前缀。

在中间件中设置SCRIPT_NAME

 # config.ru class ScriptName def initialize(app, name) @app = app @name = name end def call(env) env['SCRIPT_NAME'] += @name @app.call(env) end end use ScriptName, '/relative_root' run Rails.application 
  • 与上面的效果相同,但是
  • 要求传入的URL不包含relative_url_root

设置RAILS_RELATIVE_URL_ROOT

  • 值保存在app.config.relative_url_root configuration.rb中:41
  • 这又会影响资产路径asset_url_helper.rb:137
  • 但就我而言,就是这样
  • 特别是不影响url助手

设置config.action_controller.relative_url_root

  • ?? 可能影响资产编制?
  • 覆盖RAILS_RELATIVE_URL_ROOT env var?

明确定义/relative_root下的所有路由(rizzah的答案)

 # config/routes.rb Myapp::Application.routes.draw do scope '/relative_root' do ... end end 
  • Url助手将生成正确的URL
  • 传入的URL必须包含相对URL根(对Nginx配置敏感,见下文),否则“无路由匹配”例外
  • 请求静态资产的URL,例如/relative_root/images/logo.png将导致“无路由匹配”exception。 如果nginx无论如何都在提供静态资产,这可能不是问题。

Nginx配置

给出这样的配置:

 upstream myapp { server localhost:3000; } server { ... location /relative_root { proxy_pass http://myapp/; } } 

Nginx将删除/relative_root ,Rails应用程序将无法看到它。 如果您需要Rails应用程序,请查看它,一种方法是更改proxy_pass行:

 ... proxy_pass http://myapp/relative_root/; ...