Connecting to multiple databases
from Ruby on Rails
A recent challenge I faced while working on our product was a requirement that surfaced from a potential client who asked that they be able to use our web-based application as-is, but host their own data internally (in other words, run their own database separate from the one all of our other clients share).
My initial thought was to set-up a second sub-domain (lets call it www2.myapp.com) pointing to our rails application and add a “before_filter” to the ApplicationController that could detect which request.host was being used, and connect to the appropriate database for the remainder of the http request.
My goal here was to leave as much code untouched as I could, and avoid installing any heavy duty plugins or gems that might erupt into a support headache in the future.
While my strategy above was not far from the final solution, I did encounter some roadblocks.
My initial crack at it went something like this:
class ApplicationController < ActionController::Base
before_filter :choose_db
def choose_db
if request.host == 'www2.myapp.com'
ActiveRecord::Base.establish_connection( ... credentials go here ...)
else
ActiveRecord::Base.establish_connection :production
end
end
end
At first this appeared to work, until I noticed that when accessing www.myapp.com sessions were getting invalidated on www2.myapp.com (this could happen in both directions). With a bit of help from StackOverflow I learned that calling establish_connection at the “Class” level was actually going to interrupt all connections, and instead this needed to be called at the model level. Because I wanted to avoid touching too much code, the easiest solution was to extend ActiveRecord and have all my models extend that abstract class. Calling “establish_connection” from that abstract class would then let models choose to use that connection as needed.
Put simply I created:
class Varydatabase < ActiveRecord::Base
self.abstract_class = true
end
Then for every model in my app I extended Varydatabase instead of activerecord:
class Account < Varydatabase
….end
Now in the application controller, I simply call Varydatabase.establish_connection instead of from ActiveRecord::Base.
While this did end up working, I discovered that performance was sometimes lacking. It seems a slow or very heavy operation running on one database can often cause requests to the other to wait before connecting. I’m not sure if this is rails responding slowly at the webserver layer, or the database connection pool doesn’t switch contexts unless an operation has finished on the alternate database. Your mileage may vary.








