How to Setup Two Independent Rails Websites Using One CodeBase

4 minute read

I recently setup this site using (almost) the same rails app as my blog. I initially thought that it wouldn't be too bad updating both codebases (which both had separate svn trunks) whenever I need to make a change. How quickly I proved myself wrong. I set out to figure a way to have code.coneybeare.net and blog.coneybeare.net both point to the same rails app, but use separate databases and stylesheets. With some help from my friend Will Sobel, I was able to merge both sites into one. Here's how:
First things first... you need to figure out what host you are using:

        
@host = request.env['HTTP_HOST']
Next you setup a helper method in application.rb that all of your controllers call as a before_filter. There are 4 cases, 2 for development on local host, and two for the two domains I am hosting. In all the controllers add:

        
before_filter :choose_env
In application.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
def choose_env
  @host = request.env['HTTP_HOST']

  if @host == 'localhost:3000'
    ActiveRecord::Base.establish_connection(
      :adapter  => 'mysql',
      :database => 'blog_development',
      :username => 'root')

  elsif @host == 'localhost:3001'
    ActiveRecord::Base.establish_connection(
      :adapter  => 'mysql',
      :database => 'code_development',
      :username => 'root')

  elsif @host == 'blog.coneybeare.net'
    ActiveRecord::Base.establish_connection(
      :adapter  => 'mysql',
      :database => 'blog_production',
      :username => 'USERNAME',
      :password => 'PASSWORD',
      :host     => 'mysql.coneybeare.net')

  elsif @host == 'code.coneybeare.net'
    ActiveRecord::Base.establish_connection(
      :adapter  => 'mysql',
      :database => 'codeblog_production',
      :username => 'USERNAME',
      :password => 'PASSWORD',
      :host     => 'mysql.coneybeare.net')
  end
end
Each since this method is called as a before_filter, every request connects to the database it is supposed to. So now that the data is taken care of, we need to make sure that each site looks the way it is supposed to. In apps/views/layouts/ add two different layouts that you want to use. In my case they were nearly identical, with only the links in the headers different and (most importantly) the stylesheet link. In blog_layout.rhtml, I have:

        
<%= stylesheet_link_tag "blog_display" %>
This points any page that uses the blog_layout to use the blog_display.css. Similarily, in code_layout.rhtml I have:

        
<%= stylesheet_link_tag "code_display" %>
So now that I have the different stylesheets and layouts I have to tell the app which one to use. I added another helper method to application.rb to handle the logic, and added a line to every controller:

        
layout :choose_layout
Now I don't have a layout named choose_layout so rails will look for a method named choose_layout. Let's create that in application.rb
1
2
3
4
5
6
7
8
def choose_layout
  @host = request.env['HTTP_HOST']
  if @host == 'localhost:3000' || @host == 'blog.coneybeare.net'
    return 'blog_layout'
  elsif @host == 'localhost:3001' || @host == 'code.coneybeare.net'
    return 'code_layout'
  end
end
Now you want to make sure all the controllers can see the helper methods you made so add this to application.rb

        
helper_method :choose_env, :choose_layout
Now you should be using the right database and the right stylesheets, but what if you have more conditionals, like links or images? You can condition on @host to do whatever you want:
1
2
3
4
5
<% if @host == 'localhost:3000' || @host == 'blog.coneybeare.net' %>
  I am on the blog page
<% elsif @host == 'localhost:3001' || @host == 'code.coneybeare.net' %>
  I am on the code page
<% end %>
That's it! I have only been using this way for a day or so but it seems to be ok so far. There are some pro's and con's to this though so it might not be for everybody. Let start with the pros:
  • The obvious: I now only have one place to go to edit my code for both sites.
  • Both of my sites cache album-cover images and flickr images. Now they get to share that cached collection.
  • It makes it really easy to ensure that the sites remain consistent in layout or appearance
  • If I wanted to add another host pointing to my app, it is easy to add. Likewise, the code will work on its own and can be easily implemented on 1 host still.
Now the cons:
  • Both sites share the same resources (ram, cpu) and this might cause both sites to be a little slower, especially if I have a lot of traffic.
  • Each time a page request is made I establish a new database connection, taking a fraction of a second longer for page loads
  • I hate editing stylesheets and now I have two to maintain
  • It is hard to get stats between the two sites
All that being said, I am glad I did it because unless my sites become super popular or Dugg, I should be ok on resources, and the pros definitely outweigh the cons for me.

Was this page helpful for you? Buy me a slice of 🍕 to say thanks!

Updated:

Comments