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.

amoroz commented Oct 22, 2013

Thanks for the hook, dude.

@jtomaszewski

This comment has been minimized.

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.

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