Rails app with multiple domains
We had recently released a story, which allow one app to serve with 2 domains. I’m writing the details down if other guys need some references. Note, in our case, there’re 2 domains, this solution could also work with more than 2 domains.
I’ll start with two perspectives, Route and Business logic.
Route
We have hosts.yml
file with domains/hosts configured in it.
development: &development
site_1: site1.dev
site_2: site2.dev
staging:
...
production:
site_1: www.site1.com
site_2: www.site2.com
Load this config file while app starting, you can put this file into initializers
directory, hosts.rb
HOSTS_CONFIG = ConfigLoader.load_yml_config('config/hosts.yml', Rails.env)
puts "Site 1 Domain: #{DOMAINS_CONFIG[:site_1]}"
puts "Site 2 Domain: #{DOMAINS_CONFIG[:site_2]}"
Detect request host in Routes
- Define a custom constraint class in lib/domain_constraint.rb:
class Site1HostConstraint
def matches?
HOSTS_CONFIG[:site_1] == request.host
end
end
- Use the class in your routes with the new block syntax
constraints Site1HostConstraint.new do
root :to => "site_1#index"
end
root :to => 'main#index'
Business Logic
In order to know the current request host across the whole app, mainly including Model and View/Presenter layers. There’s one way you can pass the request.host
via controller, but I think it’s sorta complex if we pass in that object everywhere. Thus I introduced a gem called request_store, this gem allows global variable in Rails.
Set current request host in ApplicationController
- Add before filter
before_filter :set_request_host
private
def set_request_host
RequestStore.store[:host] = request.host
end
- Access current request host globally
module HostHelper
def self.host_name
RequestStore.store[:host]
end
end
Then, you can do something like HostHelper.host_name
in Model layer or Presenter layer. Also you can define methods like .site_1?
.site_2?
.etc.
Recap
By using Rails Route Constraint, you can decide which controller to go according to the request host.
With Gem request_store
, you can determine which is the current request host across whole app.
I’ll come up with more about Cookie share between domains in my next post.
References:
- http://stackoverflow.com/questions/4207657/rails-routing-to-handle-multiple-domains-on-single-application
- http://guides.rubyonrails.org/routing.html#advanced-constraints