¿Cuál es el reemplazo de ActionController :: Base.relative_url_root?

Estoy portando una aplicación de Rails 2.x a rails3; lo llamaremos foo-app. Foo-app es una sección de una aplicación de Rails más grande y vive en main_rails_app.com/foo-app. Anteriormente, solo configuramos lo siguiente en nuestra configuración de producción de foo-app para garantizar que nuestras rutas de foo-app funcionaran correctamente:

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

Sin embargo, con rails3, ahora obtengo:

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

Desde entonces, he cambiado la entrada de configuración a lo siguiente:

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

Esto funciona principalmente porque todas las llamadas a recursos externos (javascript / css / images) usarán / foo-app. Sin embargo, ninguna de mis rutas cambia apropiadamente, o dicho de otra manera, foo-app root_path me da ‘/’ cuando esperaría ‘/ foo-app’.

Dos preguntas:

  1. ¿Cuál es el reemplazo de ActionController :: Base.relative_url_root
  2. si es config.action_controller.relative_url_root, ¿por qué mis rutas no reflejan el valor relative_url_root que establecí?

Debería poder manejar todo eso dentro del archivo routes.rb. Envuelva todas sus rutas actuales en el scope; por ejemplo.

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

A continuación, puede verificar su ruta a través de las rake routes que deben mostrar sus rutas en consecuencia, incluida su raíz de contexto (raíz_url_relativa)

Si se implementa a través de Passenger, use la directiva RackBaseURI : http://www.modrails.com/documentation/Users%20guide%20Apache.html#RackBaseURI

De lo contrario, puede ajustar la instrucción de run en su config.ru con el siguiente bloque:

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

Entonces solo tiene que configurar la variable de entorno RAILS_RELATIVE_URL_ROOT en “/ foo-app”. Esto incluso se aplicará a las rutas establecidas en gems o complementos.

Advertencia: no mezcle estas dos soluciones.

Siento que debo estar complicando demasiado esto y / o faltando algo, pero este problema me ha estado frustrando por un tiempo, y aquí están mis notas.

Resumen

Hay dos problemas separados con dos puntos cada uno para las rutas dinámicas y estáticas:

  1. cómo obtener el enrutamiento para que coincida correctamente con una URL entrante
    • para rutas
    • para archivos estáticos
  2. cómo generar URLs que incluyen la raíz_relativa
    • a través de los ayudantes de url
    • para activos estáticos

Una forma de resolver los cuatro puntos:

  • Configure Nginx para quitar la porción relative_root
    • Esto resuelve la coincidencia de ruta; solo escriba rutas esperando URLs en / like development
    • También se sirven archivos estáticos como en desarrollo
  • Establecer la variable de entorno RAILS_RELATIVE_URL_ROOT
    • Esto resuelve los ayudantes de activos estáticos generados
  • Use el middleware ScriptName continuación ( ScriptName para usar el valor del entorno)
    • Esto resuelve los ayudantes de url generados, por ejemplo, users_path

Envolviendo la aplicación Rails en Rack :: URLMap en config.ru (respuesta de Christoph)

 # config.ru map '/relative_root' do run Myapp::Application end 
  • requiere una URL entrante que contenga la raíz_url_relativa (Nginx se puede configurar para eliminar o retener esto; ver a continuación)
  • Rack anexa la SCRIPT_NAME a Rack env SCRIPT_NAME rack / urlmap.rb: 62
  • Rails agrega SCRIPT_NAME la solicitud actual a url_para las opciones metal / url_for.rb: 41
  • Rails ‘url_prepends el nombre del script al generar rutas de enrutamiento / url_for.rb: 133

Para que cubra las URL generadas por los helpers de URL, por ejemplo, UserController dado, users_path estará prefijado por la raíz de url relativa.

Establecer SCRIPT_NAME en middleware

 # 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 
  • Tiene el mismo efecto que el anterior, pero
  • Requiere que la URL entrante NO contenga la raíz_url_relativa

Configuración de RAILS_RELATIVE_URL_ROOT

  • el valor se guarda en app.config.relative_url_root configuration.rb: 41
  • que a su vez afecta a las rutas de activos asset_url_helper.rb: 137
  • pero eso es todo lo que veo
  • notablemente no afecta a los ayudantes de url

Configuración config.action_controller.relative_url_root

  • ?? Puede afectar la comstackción de activos?
  • Anula RAILS_RELATIVE_URL_ROOT env var?

Definir explícitamente todas las rutas en /relative_root (respuesta de rizzah)

 # config/routes.rb Myapp::Application.routes.draw do scope '/relative_root' do ... end end 
  • Los ayudantes de URL generarán las URL correctas
  • La URL entrante debe contener la raíz de URL relativa (sensible a la configuración de Nginx, ver a continuación), de lo contrario las excepciones “no coincide con la ruta”
  • Las URL que solicitan activos estáticos, p. Ej. /relative_root/images/logo.png darán lugar a excepciones “sin coincidencias de ruta”. Esto puede no ser un problema si nginx está sirviendo activos estáticos de todos modos.

Configuración de Nginx

Dada una configuración como esta:

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

Nginx quitará la raíz /relative_root y la aplicación Rails no lo verá. Si necesita la aplicación Rails, que la vea, una forma es cambiar la línea proxy_pass :

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