What is the replacement for ActionController::Base.relative_url_root?

后端 未结 3 437
说谎
说谎 2020-11-28 08:35

I am porting a 2.x rails app to rails3; we\'ll call it foo-app. Foo-app is one section of a larger rails app and lives at main_rails_app.com/foo-app. Previously we just set

相关标签:
3条回答
  • 2020-11-28 09:16

    You should be able to handle all that within the routes.rb file. Wrap all your current routes in scope; for instance.

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

    You can then verify your routing via the rake routes they should show your routes accordingly, including your context root(relative_url_root)

    0 讨论(0)
  • 2020-11-28 09:36

    If you deploy via Passenger, use the RackBaseURI directive: http://www.modrails.com/documentation/Users%20guide%20Apache.html#RackBaseURI

    Otherwise, you can wrap the run statement in your config.ru with the following block:

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

    Then you only have to set the environment variable RAILS_RELATIVE_URL_ROOT to "/foo-app". This will even apply to routes set in gems or plugins.

    Warning: do not mix these two solutions.

    0 讨论(0)
  • 2020-11-28 09:42

    I feel like I must be over-complicating this and/or missing something, but this issue has been frustrating me for a while now, and here are my notes.

    Summary

    There are two separate issues with two points each for dynamic and static routes:

    1. how to get routing to correctly match an incoming URL
      • for routes
      • for static files
    2. how to generate URLs that include the relative_root
      • via url helpers
      • for static assets

    One way to solve all four points:

    • Configure Nginx to strip the relative_root portion
      • This solves route matching; just write routes expecting URLs at / like development
      • Also static files are served as in development
    • Set RAILS_RELATIVE_URL_ROOT environment variable
      • This solves generated static asset helpers
    • Use the ScriptName middleware below (modify it to use the value from the environment)
      • This solves generated url helpers, e.g. users_path

    Wrapping the Rails application in Rack::URLMap in config.ru (Christoph's answer)

    # config.ru
    map '/relative_root' do
      run Myapp::Application
    end
    
    • requires incoming URL contain the relative_url_root (Nginx can be configured to remove or retain this; see below)
    • Rack appends the relative_url_root to the Rack env SCRIPT_NAME rack/urlmap.rb:62
    • Rails adds the current request's SCRIPT_NAME to url_for options metal/url_for.rb:41
    • Rails' url_for prepends the script name when generating paths routing/url_for.rb:133

    So that covers URLs generated by the url helpers, e.g. given UserController, users_path will be prefixed by the relative url root.

    Set SCRIPT_NAME in 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
    
    • Has same effect as above, but
    • Requires that incoming URL NOT contain the relative_url_root

    Setting RAILS_RELATIVE_URL_ROOT

    • value is saved in app.config.relative_url_root configuration.rb:41
    • which in turn affects asset paths asset_url_helper.rb:137
    • but that's it as far as I see
    • notably does not affect url helpers

    Setting config.action_controller.relative_url_root

    • ?? May affect assets compilation?
    • Overrides RAILS_RELATIVE_URL_ROOT env var?

    Explicitly defining all routes under /relative_root (rizzah's answer)

    # config/routes.rb
    Myapp::Application.routes.draw do
      scope '/relative_root' do
        ...
      end
    end
    
    • Url helpers will generate correct urls
    • Incoming URL must contain the relative url root (sensitive to Nginx configuration, see below), else "no route matches" exceptions
    • URLs requesting static assets, e.g. /relative_root/images/logo.png will result in "no route matches" exceptions. This may not be an issue if nginx is serving static assets anyway.

    Nginx config

    Given a config like this:

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

    Nginx will strip out the /relative_root, and the Rails app will not see it. If you need the Rails app so see it, one way is to change the proxy_pass line:

    ...
        proxy_pass http://myapp/relative_root/;
    ...
    
    0 讨论(0)
提交回复
热议问题