Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rake tasks for multiple databases with different schemas

I am working on a multi-database Rails 3 application. Each database has a different schema (and in production are located in different locations). I've set the app to talk to different databases like so:

database.yml

development:
  adapter: mysql2
  encoding: utf8
  reconnect: false
  database: main_development
  pool: 5
  username: someuser
  password: somepassword
  socket: /tmp/mysql.sock

other_development:
  adapter: mysql2
  encoding: utf8
  reconnect: false
  database: other_development
  pool: 5
  username: someuser
  password: somepassword
  socket: /tmp/mysql.sock

models/other_base.rb

class OtherBase < ActiveRecord::Base
  self.abstract_class = true
  establish_connection "other_#{Rails.env}"
end

models/some_model.rb

class SomeModel < OtherBase
  # Regular stuff here
end

Now, this works fine for web app, but not so well for running rake tasks, including tests (fixtures aren't loaded correctly). Is there a gem available for this? Any help appreciated.

Also, it would be nice to create a schema.rb file that could handle the different schemas for different DBs - that is, would allow me to do things like rake db:create or db:setup and have it create multiple databases with the database-specific schema.

like image 215
Paul Avatar asked Feb 23 '11 02:02

Paul


3 Answers

I find the use of environments a non acceptable hack in this case. You want to have two databases in the same environment.

While I was researching that question myself I came across a gist of the github user rafaelchiti. Unfortunately he removed the original gist. You can find a copy of it here.

like image 110
wrtsprt Avatar answered Nov 13 '22 10:11

wrtsprt


I had the same problem, and after spending half an hour looking for the 'loopy_multiple_database' plugin, eventually concluded that it had vanished off the face of the web and resorted to monkey-patching the Rails rake tasks. The only task I wanted to fix was db:migrate, but the same (ugly) process would allow you to patch other tasks too.

On Rails 3, add create a file db_migrate_override.rake (any *.rake name will do) in lib/tasks like so:

Rake::TaskManager.class_eval do
  def remove_task(task_name)
    @tasks.delete(task_name.to_s)
  end
end

def remove_task(task_name)
  Rake.application.remove_task(task_name)
end

namespace :db do
  remove_task 'db:migrate'
  desc "Migrate the database (options: VERSION=x, SRCDIR=path, VERBOSE=false)."
  task :migrate => :environment do
    srcdir = (ENV["SRCDIR"] || "db/migrate/")
    ActiveRecord::Migrator.migrate(srcdir, ENV["VERSION"] ? ENV["VERSION"].to_i : nil)
    Rake::Task["db:schema:dump"].invoke if (ActiveRecord::Base.schema_format == :ruby && ENV['SRCDIR'].nil?)
  end
end

Then you can run

rake db:migrate RAILS_ENV=other_development SRCDIR=db_other/migrate
like image 1
David Waller Avatar answered Nov 13 '22 09:11

David Waller


You can try using octopus gem(https://github.com/thiagopradi/octopus), it helps you to setup multiple databases and is compatible with Rails 3.2 and Rails 4. With this gem you can easily specify the database you would like to run the migrations for.

like image 1
Nikhil Taneja Avatar answered Nov 13 '22 09:11

Nikhil Taneja