ruby 使用控制数据库Rails多租户/多数据库和子域

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ruby 使用控制数据库Rails多租户/多数据库和子域相关的知识,希望对你有一定的参考价值。

# app/models/migration.rb

class Migration < ActiveRecord::Base

  self.table_name = "clients"

  def self.migrate

    default = ActiveRecord::Base.connection_config

    ActiveRecord::Base.establish_connection("control")

    Migration.all.each do |client|

      ActiveRecord::Base.establish_connection(default.merge({
        "database" => client.database,
        "host"     => "..."
      }))

      ActiveRecord::Migrator.migrate(ActiveRecord::Migrator.migrations_paths)
      puts "\033[32m'#{client.name}' migrated successfully\033[0m"

    end

    ActiveRecord::Base.establish_connection(default)

  end

end
# config/deploy.rb

after "deploy:migrate", "deploy:migrate_clients"
# lib/deploy/db.rb

namespace :deploy do

  desc "Run migrate for all clients"
  task :migrate_clients do
    begin
      run "cd #{current_path} && bundle exec rails runner -e production 'Migration.migrate'"
      Capistrano::CLI.ui.say "\033[32m  * success\033[0m"
    rescue Exception => e
      Capistrano::CLI.ui.say "\033[31m  * error"
      Capistrano::CLI.ui.say "*** [err] #{e.message}\033[0m"
    end
  end

end
# app/models/client.rb

class Client < ActiveRecord::Base
  
  scope :active, where(:active => true)

  attr_accessible :active, :subdomain, :database, :host, etc...

end
# app/controllers/application_controller.rb

class ApplicationController < ActionController::Base

  before_filter :select_database

  protected

  def select_database
    ActiveRecord::Base.establish_connection("control")
    active_client = Client.active.where(:subdomain => subdomain).first
    if !!active_client
      begin
        config = ActiveRecord::Base.connection_config.merge({
          :database => active_client.database,
          :host     => "...",
          :username => "...",
          :password => "..."
        })
      rescue
        ActiveRecord::Base.establish_connection("production")
        # database connection error
        # flash, log, redirect, etc
      end
    else
      # inactive client or client not found
      # flash, log, redirect, etc
    end
  end

  def subdomain
    !request.subdomain.empty? && request.host != "mydomain.com" ? request.subdomains.first : ""
  end

end
# config/application.rb

module MyApp
  class Application < Rails::Application

    def config.database_configuration

      config = super

      ActiveRecord::Base.establish_connection(config["control"])

      Migration.all.each do |client|
        config[client.subdomain] = config["control"].merge("database" => client.database, "host" => "...")
      end

      ActiveRecord::Base.establish_connection(config[Rails.env])

      return config
    end

  end
end

以上是关于ruby 使用控制数据库Rails多租户/多数据库和子域的主要内容,如果未能解决你的问题,请参考以下文章

使用 PostgreSQL 的模式和 Rails 创建多租户应用程序

使用Apartment gem的Rails多租户

实现saas多租户方案比较

Ruby on Rails:一对多关系视图

在 ruby​​ on rails 中以一对多关系创建新记录

ABP Zero 单部署,单数据库,多租户架构