Rails Multiple Databases
There are a few tricks to integrating a rails app with a multiple database, especially if you involve a gem. Here is a summary of the situation I was in.
- Building a Rails Application that had it's own database
- But also required access to a (MSSQL) financial system's database; to get customer data
- I used ActiveRecord and additionally packaged the code in a gem for reuse in other applications
I built a standard gem and included an abstract base class for establishing a connection to the financial system. All active record models will extend this base class and therefore share the connection details.
# /lib/financial/system/financial_system_active_record_base.rb module Financial::System class FinancialSystemActiveRecordBase < ActiveRecord::Base self.abstract_class = true end end
In the Gem Module I created a method to configure the database connection. Note the workaround I had to use because of this lousy bug
# /lib/financial/system.rb module Financial module System def self.configure(yml_config) # first gotcha if ActiveRecord::Base.connected? FinancialSystemActiveRecordBase.establish_connection(yml_config) else ActiveRecord::Base.establish_connection(yml_config) end end end end
The Rails App
The Rails App has the usual stock stuff including a database.yml for it's own database.
Initialize the Gem
I created an initializer to configure the Financial Systems gem. The previous workaround (in the gem) causes problems with automated tests in the Rails app. I explain below, but here is how I got through it.
# /config/initializer/financial_system.rb module RailsAppName class Application < Rails::Application config.after_initialize do yml_config = YAML.load_file(Rails.root.join('config/financial_system_config.yml'))[Rails.env] Financial::System.configure(yml_config) end end end
Replace RailsAppName with whatever your module is called in config/application.rb. I had to run this code 'afterinitialize' so automated tests would NOT point the Rails App's models at the Financial Systems database. But rather only configure the Gem's models. Before this fix my tests would throw an error saying "cannot find the table ___" and no it was not due to any lack of running 'rake db:test:prepare'. :)
Eventually I used this gem in more than one rails app and needed the Financial Systems factory girl settings in both. So I created a class in the Gem to configure the factories
# in the gem module Financial::System class Factories def self.define(factoryGirl) factoryGirl.define do factory :contact, :class => Financial::System::Contact do sequence :contactid contactname 'Some Name' phoneno1 '1112223333' phoneno2 '' emailaddress 'email@example.com' end end end end end
Things to note
- I passed in the module FactoryGirl
- I had to associate the factory with the Gems Active Record Model
I used the factories in the rails app; Place the following code at the very bottom regardless of if you are using spork / guard, and you'll be good to go.
# /test/test_helper.rb Financial::System::Factories.define(FactoryGirl)