Автоматическое переключение баз данных из приложения rails изящно из ApplicationController? - PullRequest
3 голосов
/ 24 марта 2010

Я видел этот пост несколько раз, но так и не нашел ответа на этот конкретный вопрос.

Я бы хотел запустить приложение rails, основанное на обнаруженном request.host (представьте, что у меня есть два дочерних домена, указывающих на один и тот же ip-адрес приложения и сервера rails: myapp1.domain.com и myapp2.domain.com).

Я пытаюсь, чтобы myapp1 использовал стандартную «производственную» базу данных, а запросы myapp2 всегда используют альтернативную удаленную базу данных. Вот пример того, что я пытался сделать в Контроллере приложений, который не работал:

class ApplicationController < ActionController::Base
  helper :all 
  before_filter :use_alternate_db

  private

    def use_alternate_db

      if  request.host == 'myapp1.domain.com'
        regular_db
      elsif request.host == 'myapp2.domain.com'
        alternate_db
      end

    end

    def regular_db
      ActiveRecord::Base.establish_connection :production
    end

    def alternate_db
      ActiveRecord::Base.establish_connection(
      :adapter => 'mysql',
      :host => '...',
      :username => '...',
      :password => '...',
      :database => 'alternatedb'
      )

    end
end

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

Дополнительная сложность заключается в том, что я использую Heroku в качестве хостинг-провайдера, поэтому у меня нет контроля на уровне сервера приложений apache / rails.

Я смотрел на такие решения, как dbcharmer и magicmodels, но ни один из них, похоже, не дает примеров того, как я это делаю. Спасибо за любую помощь!

1 Ответ

4 голосов
/ 25 марта 2010

Я отключаю эту строку от вашего вопроса:

все соединения (включая действительные сеансы через разные субдомены прерываются ...).

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

Вы можете сделать это, вставив новый класс между ActiveRecord и моделями, для которых вы хотите изменить, изменить соединение.

Этот класс будет выглядеть так:

class MyAppModel < ActiveRecord::Base
  self.abstract_class = true
end

тогда модели, которые должны быть изменены, должны наследоваться от него:

class User < MyAppModel
  #stuff
end

Модели, которые не должны изменяться, должны оставаться подключенными к ActiveRecord.

Наконец, в вашем ApplicationController, вызовите вместо этого установочную_коннекцию в MyAppModel.

Вы можете сделать это с таким количеством классов, сколько захотите. Классы Model будут работать обратно вверх по иерархии, пока не найдут первый класс с допустимым соединением, и будут использовать его для взаимодействия с базой данных. Никаких других изменений не требуется.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...