Rails: Multitenant db:migrate

A multitenant approach using Postgres schemas depends on domain discovery through application url and then schema mapping for the discovered domain. However, how do you convince Rails to run applications for all the tenants?

One solution is to overwrite the db_migrate task forces the task to touch all of the tenants, setting the search path accordingly for each tenant:


db_tasks.each do |task_name|
  Rake::Task[task_name].enhance(["multitenant:#{task_name}"])
end

The heavy lifting accomplished by the multitenant version:


namespace :multitenant do
  desc "A rake task for multitenancy and the executing the existing db tasks"
  db_tasks.each do |task_name|
    desc "Run #{task_name} for each tenant"
    task task_name => %w[environment db:load_config] do
      ActiveRecord::Base.establish_connection(@config)
      #Rake::Task[task_name].execute
      if task_name == 'db:migrate'
        Rake::Task['multitenant:perform_null_migration'].execute if ENV['PERFORM_NULL_MIGRATION']
        Rake::Task['multitenant:set_up_tenants_for_test_suite'].execute
      end
      if (ActiveRecord::Base.connection.table_exists? 'tenants')
        if Tenant.count == 0
          tenants = TENANT_CONFIG.keys - %w[defaults paypal]
          tenants.each do |k|
            Tenant.create! name: k.capitalize, subdomain: k
            p "Created tenant: #{k}"
          end
        end
        Tenant.order(:subdomain).each do |tenant|
          puts "Running #{task_name} for #{tenant.subdomain} "
          tenant.scope_schema_tenant_only {
            Rake::Task[task_name].execute
          }
          success = PgTools.drop_public_only_tables(tenant.subdomain)
          puts "========== Dropped Public Only tables for #{tenant.subdomain} ==========" if success
        end
      end
      success = PgTools.drop_tenant_only_tables
      puts "========== Dropped Tenant Only tables in Public ==========" if success
    end
  end