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

时间:2010-07-05 19:26:53

标签: ruby-on-rails ruby-on-rails-3

我正在将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. 的替代品是什么?
  3. 如果是config.action_controller.relative_url_root,那么为什么我的路线没有反映我设定的relative_url_root值?

3 个答案:

答案 0 :(得分:19)

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

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

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

答案 1 :(得分:13)

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

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

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

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

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

答案 2 :(得分:5)

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

摘要

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

  1. 如何使路由正确匹配传入的URL
    • for routes
    • for static files
  2. 如何生成包含relative_root的网址
    • 通过网址助手
    • for static assets
  3. 解决所有四点的一种方法:

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

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

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

    因此,它涵盖了网址助手生成的网址,例如给定UserControllerusers_path将以相对网址为前缀。

    在中间件

    中设置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
    
    • 与上述效果相同,但
    • 要求传入的网址不包含relative_url_root

    设置RAILS_RELATIVE_URL_ROOT

    设置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根(对Nginx配置敏感,见下文),否则“无路由匹配”例外
    • 请求静态资产的网址,例如/relative_root/images/logo.png将导致“无路由匹配”异常。如果nginx无论如何都在提供静态资产,这可能不是问题。

    Nginx config

    给出这样的配置:

    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/;
    ...