views:

356

answers:

2

I run a Rails app, and we're in the process of splitting out our signup process to a separate app. The signup app has its own separate database (for CMS and collecting prospects), but it also needs to have access to the main database. This works really well using ActiveRecord::Base.establish_connection.

However, I'd like to be able to write some specs. The trouble is, how can I write specs/tests without clearing out my development database every time my tests run? If I go into the console in test mode, it's obvious the the test mode is hooked into the development database from my main app.

Here's what my database.yml file looks like:

development: 
  database: signup_dev

test:
  database: signup_test

main_app_dev: 
  database: main_app_dev

main_app_test: 
  database: main_app_test

Based on this file, I'd like establish_connection to connect to connect to the database my_app_dev in development mode, and my_app_test in test mode. Any ideas?

A: 

We have a gem that is basically a collection of ActiveRecord models that connect to our legacy system. In our case we have all those models contained in a module from which all models related to the legacy database connects.

module Legacy
  class Base < ActiveRecord::Base
    establish_connection :legacy
  end

  class User < Base
  end
end

With this setup it makes it really easy to switch out the database connection. If you really go for that automated detection you can put logic in your base class to determine which database to use:

module Legacy
  class Base < ActiveRecord::Base
    if Rails.env == 'test'
      establish_connection :legacy_test
    else
      establish_connection :legacy
   end
end

Or simply tell your module which connection to use in your spec helper:

# spec/spec_helper.rb    
Legacy::Base.establish_connection(ActiveRecord::Base.configurations['legacy_test'])

Personally I would recommend the second option. Of course both solutions depend on namespaced models.

Peer

Peer Allan
Thanks Peer - I like the Legacy wrapper - that seems to encapsulate the legacy models really nicely. Before I saw your response I tried extending ActiveRecord with a mixin. This worked pretty well, but I like your idea of using the `ActiveRecord::Base.configurations`. I'll post what I came up with below as an answer.
Ryan Heneise
A: 

Here's what I came up with as a mixin:

# lib/establish_connection_to_master_database.rb
module EstablishConnectionToMasterDatabase
  def establish_connection_to_master_database

    case RAILS_ENV
    when "development"
      establish_connection :master_dev
    when "test"
      establish_connection :master_test
    when "production"
      establish_connection :master
    end

  end
end
ActiveRecord::Base.send(:extend, EstablishConnectionToMasterDatabase)

# models/subscription.rb
class Subscription < ActiveRecord::Base
  establish_connection_to_master_database
end

# config/initializers/config.rb
require 'establish_connection_to_master_database'

In order for this to work with RSpec, this needs to be loaded in an initializer - apparently loading it in the environment file causes it to be loaded it too late, and it won't work.

Ryan Heneise