Beesbot

Rails Multiple Databases

Oct 20, 2014

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.

The Gem

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'. :)

Factory Girl

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 'name@email.com'
                end
            end
        end
    end
end

Things to note

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)