Несколько соединений с базой данных в Rails - PullRequest
2 голосов
/ 24 января 2010

Я пишу более простую версию phpMyAdmin в Rails; это веб-приложение будет работать на веб-сервере (где пользователи смогут указывать имя базы данных, имя хоста, имя пользователя, пароль и номер порта одного из серверов базы данных, работающих в той же сети). Затем пользователь будет подключен к этому компьютеру и сможет использовать пользовательский интерфейс для администрирования этой базы данных (добавлять или удалять столбцы, удалять таблицы и т. Д.).

У меня есть два связанных вопроса (ваша помощь очень поможет мне понять, как лучше всего к этому подойти):

  1. В традиционном приложении на Rails я храню информацию о базе данных в database.yml, однако здесь мне нужно делать это динамически. Есть ли хороший способ оставить файл database.yml пустым и указать Rails вместо этого использовать данные соединения, предоставленные пользователем во время выполнения?

  2. Разные пользователи могут подключаться к разным базам данных (или даже к хостам). Я предполагаю, что мне нужно отслеживать связь между установленным подключением к базе данных и сеансом пользователя. Какой лучший способ добиться этого?

Заранее спасибо.

1 Ответ

2 голосов
/ 24 января 2010
  1. Чтобы запретить Rails инициализировать ActiveRecord с помощью database.yml, вы можете просто удалить :active_record из config.frameworks в config / environment.rb. Затем, чтобы установить соединение вручную, вы используете ActiveRecord::Base.establish_connection. (А может и ActiveRecord::Base.configurations)

    ActiveRecord хранит все соединения, связанные с переменными класса. Поэтому, если вы хотите динамически создавать несколько соединений, вам также необходимо динамически создать подкласс ActiveRecord :: Base и вызвать для этого файл assign_connection.

    Это будет ваш абстрактный базовый класс для любого подкласса, который вы будете использовать для фактического управления таблицами. Чтобы ActiveRecord знал об этом, вы должны сделать self.abstract_class = true в определении базового класса.

    Затем каждая таблица, которой вы хотите управлять, в свою очередь динамически подклассирует этот новый абстрактный базовый класс.

  2. Это сложнее, потому что вы, конечно, не можете сохранять связи. Непосредственное решение, о котором я могу подумать, - сохранить уникальный токен в сеансе и использовать его в before_filter, чтобы вернуться к динамическому подклассу ActiveRecord :: Base, который вы, вероятно, будете где-то хранить в хэше.

    Это становится более интересным, когда вы запускаете несколько рабочих процессов Rails:

    • Вам придется хранить всю информацию о подключении к базе данных в сеансе, чтобы другие работники могли ее использовать.
    • Возможно, вам нужен согласованный уникальный токен для рабочих, поэтому используйте хеш-функцию для комбинации параметров подключения к базе данных.
    • Поскольку рабочий может быть вызван с токеном, о котором он еще не знает, ваша логика подкласса и установите_соединение, вероятно, произойдет в before_filter. (Вместо момента входа, например.)
    • Вам нужно будет придумать какой-нибудь умный способ сбора мусора для соединений и классов, когда пользователь не выходит из системы должным образом и сеанс истекает. (Извините, я этого не знаю.)
...