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

ynk*_*nkr 20 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"
Run Code Online (Sandbox Code Playgroud)

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

DEPRECATION WARNING: ActionController::Base.relative_url_root is ineffective. Please stop using it.
Run Code Online (Sandbox Code Playgroud)

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

config.action_controller.relative_url_root = "/foo-app"
Run Code Online (Sandbox Code Playgroud)

这主要是因为对外部资源(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值?

小智 19

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

scope "/context_root" do
   resources :controller
   resources :another_controller
   match 'welcome/', :to => "welcome#index"
   root :to => "welcome#index"
end
Run Code Online (Sandbox Code Playgroud)

然后,您可以通过相应的方式验证您的路由rake routes,包括您的上下文根(relative_url_root)

  • @tobinjim我发现除了在路由器中包装路由之外,我还需要设置`RAILS_RELATIVE_URL_ROOT`环境变量.然后我使用`scope ENV ['RAILS_RELATIVE_URL_ROOT'] || '/'do`以便localhost:3000在没有/ context_root的情况下仍然可以在开发中工作. (15认同)
  • 如果您不想在配置/路由中添加前缀,但这取决于您的环境,该怎么办?例如,我的单个域名有/ rails和/ rails-staging前缀:每个域名都代理到不同的Rails集群.我只是在我的config/environments/*.rb等中设置config.relative_url_root来帮助我管理所有这些,并且url刚刚起作用.这是一个很好的每环境网址前缀现在已经消失:-( (4认同)
  • 这很有用,但是,对于您的开发环境与生产环境,您如何以不同的方式应用它?我的开发环境不需要像生产环境那样落后于反向代理. (2认同)

Chr*_*nig 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
Run Code Online (Sandbox Code Playgroud)

然后你只需要将环境变量设置RAILS_RELATIVE_URL_ROOT为"/ foo-app".这甚至适用于在宝石或插件中设置的路线.

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


Pat*_*ick 5

我觉得我必须使这个问题变得过于复杂和/或缺少某些东西,但是这个问题已经让我感到沮丧了一段时间,以下是我的笔记。

摘要

对于动态和静态路由,存在两个单独的问题,分别有两点:

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

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

  • 配置Nginx剥离relative_root部分
    • 这解决了路由匹配;只需在/类似的开发中写出期望URL的路由
    • 静态文件也用作开发中的文件
  • 设置RAILS_RELATIVE_URL_ROOT环境变量
    • 这解决了生成的静态资产助手
  • 使用ScriptName下面的中间件(对其进行修改以使用环境中的值)
    • 这解决了生成的URL帮助器,例如 users_path

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

# config.ru
map '/relative_root' do
  run Myapp::Application
end
Run Code Online (Sandbox Code Playgroud)

这样就涵盖了由url helper生成的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
Run Code Online (Sandbox Code Playgroud)
  • 具有与上述相同的效果,但是
  • 要求传入URL不包含relative_url_root

设定RAILS_RELATIVE_URL_ROOT

设置 config.action_controller.relative_url_root

  • ?? 可能会影响资产编制?
  • 是否覆盖RAILS_RELATIVE_URL_ROOT环境变量?

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

# config/routes.rb
Myapp::Application.routes.draw do
  scope '/relative_root' do
    ...
  end
end
Run Code Online (Sandbox Code Playgroud)
  • 网址助手会生成正确的网址
  • 传入URL必须包含相对URL根(对Nginx配置敏感,请参见下文),否则“没有路由匹配”异常
  • 请求静态资产的URL,例如/relative_root/images/logo.png将导致“没有路由匹配”异常。如果nginx仍在提供静态资产,这可能不是问题。

Nginx配置

给定这样的配置:

upstream myapp {
  server localhost:3000;
}

server {
  ...
  location /relative_root {
    proxy_pass http://myapp/;
  }
}
Run Code Online (Sandbox Code Playgroud)

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

...
    proxy_pass http://myapp/relative_root/;
...
Run Code Online (Sandbox Code Playgroud)