Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
RAILS_RELATIVE_URL_ROOT

RAILS_RELATIVE_URL_ROOT

Rails

By default RAILS_RELATIVE_URL_ROOT is used only for asset pipeline.

To namespace your rails routes you need to wrap run MyApp::Application with map in your config.ru:

map ENV['RAILS_RELATIVE_URL_ROOT'] || "/" do
  run MyApp::Application
end

Make sure sprockets is up to date >= 2.2.2.backport1, had problems with older versions.

Gemfile (required only for rails 3.x):

gem 'sprockets', '2.2.2.backport1'

Now you can fire up the rails server using:

$ RAILS_RELATIVE_URL_ROOT=/sub rails server

If you change the RAILS_RELATIVE_URL_ROOT you need to make sure to rm -rf tmp/cache first.

ActionMailer

You will need to add :script_name to default_url_options in config/environments/*.rb:

config.action_mailer.default_url_options = { :host => 'localhost:3000', :script_name => Rails.application.config.relative_url_root }

Capistrano

In production you are probably precompiling assets, but they will not be prefixed with the url, the fastest way is just to symlink public/sub to public.

config/deploy.rb:

set :default_environment, {
  "RAILS_RELATIVE_URL_ROOT" => "/sub"
}

after "deploy:assets:precompile", "deploy:symlink_relative_public"

namespace :deploy do
  task :symlink_relative_public, :roles => :app do
    root_url = default_environment["RAILS_RELATIVE_URL_ROOT"]
    if root_url
      root_dir = root_url.split("/")[0..-2].join("/")
      run "mkdir -p #{latest_release}/public#{root_dir}" if root_dir.present?
      run "ln -nfs #{latest_release}/public #{latest_release}/public#{root_url}"
    end
  end
end

RSpec

By default tests will ignore RAILS_RELATIVE_URL_ROOT and if you want to make sure that tests work with /sub and there are no hard-coded paths in your app, you can fix this by creating spec/support/relative_url.rb

# http://stackoverflow.com/questions/5016690/making-rails-tests-aware-of-rack-middleware-outside-railss-internal-chain
Capybara.app = Rack::Builder.new do
  eval File.read(Rails.root.join('config.ru'))
end

# Fix route helpers in tests (e.g. root_path, ...)
module RelativeUrl
  extend ActiveSupport::Concern

  included do
    default_url_options[:script_name] = Rails.application.config.relative_url_root
  end
end

RSpec.configure do |config|
  config.include RelativeUrl, :type => :feature
end

Now you can run the specs using

$ RAILS_RELATIVE_URL_ROOT=/sub rspec
@amoroz

This comment has been minimized.

Copy link

@amoroz amoroz commented Oct 22, 2013

Thanks for the hook, dude.

@jtomaszewski

This comment has been minimized.

Copy link

@jtomaszewski jtomaszewski commented Nov 1, 2013

Yeah, this works great.

It'll cause you pain with some gems later too - for example, I had to tweak ApiTaster manually with a pull request.

Another example: to make CarrierWave urls work properly, I had to add in its' initializer:

  config.base_path = Rails.application.config.relative_url_root
@dgwmfo

This comment has been minimized.

Copy link

@dgwmfo dgwmfo commented Mar 25, 2014

I'm wondering if this is the answer to several problems I'm having.

My app is deployed on an internal server at http://ww.xx.yy.zz/appname.

URLS such as http://ww.xx.yy.zz/appname/users/1/dashboard work no problem. But foundation--icons-sass-rails icons appear as empty squares, and my homepage background image is broken (it appears for a fraction of a second before the broken image icon is displayed.) The filenames in both basic and digested versions are visible in rails_root/current/public/assets, but they don't seem to be findable.

Any ideas? Would setting rails_relative_url_root be relevant to these issues?

Thanks,

Dean

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment