Cайт веб-разработчика, программиста Ruby on Rails ESV Corp. Екатеринбург, Москва, Санкт-Петербург, Новосибирск, Первоуральск

Админка на Ruby on Rails

Работа одновременно с несколькими базами данных в 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 способах, возможно использовать довольно мощный механизм работы с произвольными базами данных, а не только одновременно работать с несколькими базами данных.