Rails 4: Use Multiple Databases

The idea was to have a rails application that could run multiple times.

They all have their own state, but share some data.

For this example say you have some instances of a game. The games don’t interact with each other. Lets imagine them as different game worlds.
A user should be able to use different worlds or can at least switch between them. Therefore it was required to have some kind of master data for the user accounts.

There are several descriptions out there. But I run into issues with db migrations. In production this is not such a big deal. In development and test you need migrations. Several programmers need to have the same state.
I didn’t like the idea to overwrite the the rake task.

I tried to make it easier for me and more understandable for others. You decide if it is good approach. It is my first rails project 🙂

app/models/masterdata.rb

class Masterdata < ActiveRecord::Base
  self.abstract_class = true
  establish_connection "#{Rails.env}_masterdata".to_sym
end

app/models/users.rb

class User < Masterdata
  [...]
end

config/database.yml

default: &default
  adapter: sqlite3
  pool: 5
  timeout: 5000

development:
  <<: *default
  database: db/development.sqlite3

development_masterdata:
  <<: *default
  database: db/development_masterdata.sqlite3

test:
  <<: *default
  database: db/test.sqlite3

test_masterdata:
  <<: *default
  database: db/test_masterdata.sqlite3

production:
  […]

production_masterdata:
  […]

Nothing special until here. All other tutorials will tell you now to overwrite the rake task or change the file in db/migrate/
I choose a different solution

The migration is done for both environments (test and test_masterdata). Both databases will have the same schema. Or application will some of them in the different database. We can just delete the other tables if we don’t want to have them.
We don’t have the option to do additional migrations afterwards, because the tables are missing. In that case I delete the test and dev databases
You can as well keep the tables and it works fine. You need to trust your programming skills that you don’t accidental put data into that tables. So at least in the beginning you should delete them and verify that your rails application is still working as expected.

scripts/init_dev_test_environment.sh

rake db:migrate RAILS_ENV=test
rake db:migrate RAILS_ENV=test_masterdata
sqlite3 db/test.sqlite3 "drop table users;"
sqlite3 db/test_masterdata.sqlite3 "drop table games;"

rake db:migrate RAILS_ENV=development
rake db:migrate RAILS_ENV=development_masterdata
sqlite3 db/development.sqlite3 "drop table users;"
sqlite3 db/development_masterdata.sqlite3 "drop table games;"

If you have a lot of tables I suggest to use a loope here.

for env in test development; do
  [...]
  rake db:migrate RAILS_ENV=${env}_masterdata
  [...]
done

Not elegant, not very fancy, but a good workaround for me.
In my opinion it is still better to do it in a script, than messing around with the rails default behavior.

Tagged