Если вы можете контролировать и настраивать каждый экземпляр Rails, и вы можете позволить себе тратить ресурсы из-за того, что они находятся в режиме ожидания, избавьте себя от некоторых проблем и просто измените database.yml, чтобы изменить соединение с базой данных, используемое в каждом экземпляре. Если вы беспокоитесь о производительности, этот подход не снизит ее.
Для моделей, привязанных к единственной уникальной таблице только в одной базе данных, вы можете вызвать внутри модели установить_связь:
establish_connection "database_name_#{RAILS_ENV}"
Как описано здесь: http://apidock.com/rails/ActiveRecord/Base/establish_connection/class
Некоторые модели будут использовать таблицы из одной базы данных, а другие модели - таблицы из других баз данных.
Если у вас есть идентичные таблицы, общие для разных баз данных и совместно используемые одной моделью, ActiveRecord вам не поможет. Еще в 2009 году я требовал этого в проекте, над которым работал, используя Rails 2.3.8. У меня была база данных для каждого клиента, и я назвал базы данных с их идентификаторами. Поэтому я создал метод для изменения соединения внутри ApplicationController:
def change_database database_id = params[:company_id]
return if database_id.blank?
configuration = ActiveRecord::Base.connection.instance_eval { @config }.clone
configuration[:database] = "database_name_#{database_id}_#{RAILS_ENV}"
MultipleDatabaseModel.establish_connection configuration
end
И добавил этот метод как before_filter для всех контроллеров:
before_filter :change_database
Таким образом, для каждого действия каждого контроллера, когда params [: company_id] определен и установлен, он изменит базу данных на правильную.
Для обработки миграций я расширил ActiveRecord :: Migration с помощью метода, который ищет всех клиентов и повторяет блок с каждым ID:
class ActiveRecord::Migration
def self.using_databases *args
configuration = ActiveRecord::Base.connection.instance_eval { @config }
former_database = configuration[:database]
companies = args.blank? ? Company.all : Company.find(args)
companies.each do |company|
configuration[:database] = "database_name_#{company[:id]}_#{RAILS_ENV}"
ActiveRecord::Base.establish_connection configuration
yield self
end
configuration[:database] = former_database
ActiveRecord::Base.establish_connection configuration
end
end
Обратите внимание, что, выполнив это, вы не сможете выполнять запросы в рамках одного и того же действия из двух разных баз данных. Вы можете снова вызвать change_database , но это будет неприятно, если вы попытаетесь использовать методы, выполняющие запросы, из объектов, больше не связанных с правильной базой данных. Кроме того, очевидно, что вы не сможете объединить таблицы, принадлежащие разным базам данных.
Для правильной обработки ActiveRecord должен быть значительно расширен. На данный момент должен быть плагин, чтобы помочь вам с этой проблемой. Быстрое исследование дало мне это:
DB-Charmer: http://kovyrin.github.com/db-charmer/
Я готов попробовать. Дайте мне знать, что работает для вас.