Victor Blaga
Victor Blaga

Reputation: 1862

Migrations with a Rails multiple database configuration

I'm developing a Rails application in which I will use 2 different databases. Namely one for storing user credentials and another one for storing other type of data. I've setup my database.yml file to accept 2 different databases, for each environment. It looks like this:

<% %w(development test production).each do |env| %>
data_<%= env %>:
  adapter: sqlite3
  database: db/data/<%= env %>.sqlite3
  pool: 5
  timeout: 5000

users_<%= env %>:
  adapter: sqlite3
  database: db/users/<%= env %>.sqlite3
  pool: 5
  timeout: 5000
<% end %>

I also created to 2 level models, one for each database connection, namely:

class UsersBase < ActiveRecord::Base
  establish_connection "users_#{RAILS_ENV}"
end

and

class DataBase < ActiveRecord::Base
  establish_connection "data_#{RAILS_ENV}"
end

I've some issues while generating a model, because it couldn't find the standard "development" database but I've solved that by running the generate model with the --parent option set to the appropriate class.

However, now I have a problem while trying to run rake db:migrate. The rake task doesn't find the default development database (which is by convention should be named development in database.yml). My question is if it is possible to somehow supply this as a parameter to the rake task, or even better to signal Rails somewhere in the configuration script that there are 2 databases, or that the default name of the development database is changed?

Upvotes: 2

Views: 1407

Answers (2)

sethcall
sethcall

Reputation: 2897

I wrote pg_migrate for this use-case. You can define your schemas outside of your Rails app with this project, but still natively integrate it with your Rails app (pg_migrate can output a 'schema gem', that is just your schemas and a class/cli to migrate it). Usage of this does imply dropping db:migrate as part of your development process.

The web app doesn't necessarily 'own' the schema. Also, you may program in multiple languages.

Postgres-only, though.

Upvotes: 0

ffoeg
ffoeg

Reputation: 2336

You are defining these databases:

  1. data_development
  2. users_development
  3. data_test
  4. users_test
  5. data_production
  6. users_production

Rails is looking first for database defns that match the environment name (development, test, production). For you data dbs, just use those names and the data db will be migrated.

try

<% %w(development test production).each do |env| %>
  <%= env %>:
  adapter: sqlite3
  database: db/data/<%= env %>.sqlite3
  pool: 5
  timeout: 5000

users_<%= env %>:
  adapter: sqlite3
  database: db/users/<%= env %>.sqlite3
  pool: 5
  timeout: 5000
<% end %>

all "data_X" dbs will just carry the name of the environment. This is what Rails expects and thus migrations will work on them.

That might leave you out in the cold though w/respect to migrating the users dbs. I don't think Rails migrations were intended to be used this way - migrating 2 dbs in one environment.

That said, I would try it out. Here is the model change needed to align with the database.yml change above:

class DataBase < ActiveRecord::Base
end

In fact you can do away with DataBase altogether and just have former DataBase models extend ActiveRecord::Base directly.

Interested to see what you find if you try this out.

Upvotes: 1

Related Questions