Работа одновременно с несколькими базами данных в Ruby on Rails
Обычно на сайте, в веб-приложении работа ведется с моделями (таблицы) одной базы данных. Но иногда возникает необходимость работать с несколькими базами данных одновременно, например, централизованная обработка данных нескольких источников (баз данных), распределенная система, система с резервным хранением данных и т.п.
В базовой конфигурации приложения Ruby on Rails такой возможности не предусмотрено, но это не значит, что такой возможности нет. Мало того, существует несколько способов.
Суть заключается в использовании метода класса ActiveRecord::Base establish_connection. Метод, как описано в документации, принимает хэш параметров соединения в качестве параметра. Но может быть так же передана и строка. Я использую MySQL, поэтому буду описывать параметры именно для работы с этой СУБД.
Способ 1
Как известно, конфигурация параметров соединения с базой данных (наименование базы данных, имя пользователя, пароль) хранится в файле config/database.yml, в котором прописаны параметры для каждого вида окружения, стадии разработки приложения - разработка, тестирование и готовая версия.
Но, что самое интересное, можно добавить собственный раздел в файл config/database.yml, например:
production: adapter: mysql2 encoding: utf8 reconnect: false database: dbname # основная база данных pool: 5 username: user password: pass1 socket: /var/run/mysqld/mysqld.sock # далее наш дополнительный раздел: another: adapter: mysql2 encoding: utf8 reconnect: false database: dbanother # другая база данных pool: 5 username: user2 password: pass12 socket: /var/run/mysqld/mysqld.sock
И, собственно, ради чего все эти операции? Вот тут начинается самое интересное. Мы можем определить модель, которая будет использовать наше соединение (с другой базой данных):
class Another < ActiveRecord::Base
  self.table_name = "mytable" # конечно, мы можем дополнительно
                              # уточнить и имя таблицы
  self.establish_connection "another" # это наименование именно
                                      # нашего раздела,
                                      # описывающего соединение
  ...
end
Теперь, работая с нашей моделью Another, мы будем работать с базой данных dbanother, в то время как остальные модели все так же будут продолжать использовать основную базу dbname. Довольно удобно, не правда ли?
Для каждой стадии разработки мы точно так же можем создать собственный раздел нашей отдельной базы данных:
another_development: adapter: mysql2 ... another_test: adapter: mysql2 ... another_production: adapter: mysql2 ...
Изменим определение нашей модели:
class Another < ActiveRecord::Base
  ...
  # для использования различных версий 
  # на различных стадиях разработки:
  self.establish_connection "another_#{Rails.env}" 
  ...
end
Способ 2
Возможно указание параметров соединения непосредственно в определении модели:
class Another < ActiveRecord::Base
  self.establish_connection(
    :adapter   => 'mysql2',
    :host      => 'localhost',
    :database  => 'dbanother',
    :username  => 'user2',
    :password  => 'pass12'
  )
  ...
end
Способ 3
Возможно так же указание параметров соединения непосредственно перед использованием:
class Another < ActiveRecord::Base ... end ... # далее по коду, перед использованием Another.establish_connection( :adapter => 'mysql2', :host => 'localhost', :database => 'dbanother', :username => 'user2', :password => 'pass12' ) ... @query = Another.limit(10).all
Таким образом, как можно видеть во 2 и 3 способах, возможно использовать довольно мощный механизм работы с произвольными базами данных, а не только одновременно работать с несколькими базами данных.