Соединение Rails 3.1 с несколькими базами данных - PullRequest
77 голосов
/ 25 мая 2011

В ShowNearby мы сделали очень большой переход на RoR 3.1 с PHP и столкнулись с несколькими проблемами, которые, возможно, некоторые из вас уже решали ранее.

У нас большие объемы данных, и мы решили разделить нашу БД на несколько БД, которые мы можем обрабатывать отдельно.Например, наши учетные записи, места, журналы и другие разделены на несколько баз данных

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

  • одна модель должна относиться к одной таблице в одной из баз данных.
  • rake db: drop - отбрасывать все базы данных envмы указываем в database.yml
  • rake db: create - следует создать всю базу данных env, указанную в database.yml
  • rake db: migrate - следует выполнить миграцию в различные базы данных
  • rake db: test - следует захватывать приборы и помещать их в различные базы данных и тестировать модуль / функцию / etc

Мы рассматриваем возможность установки отдельных проектов rails для каждой базы данных и подключения их к ActiveResource,но мы считаем, что это не очень эффективно.Кто-нибудь из вас сталкивался с подобной проблемой раньше?

Большое спасибо !!

Ответы [ 6 ]

142 голосов
/ 25 мая 2011

В ответ на Wukerplank вы также можете поместить данные о соединении в database.yml, как обычно, с таким именем:

log_database_production:
  adapter: mysql
  host: other_host
  username: logmein
  password: supersecret
  database: logs

Затем в вашей специальной модели:

class AccessLog < ActiveRecord::Base
  establish_connection "log_database_#{Rails.env}".to_sym
end

Чтобы эти противные учетные данные не были в коде вашего приложения.

Редактировать: Если вы хотите повторно использовать это соединение в нескольких моделях, вы должны создать новый абстрактный класс и наследовать от него, потому чтосоединения тесно связаны с классами (как объяснено здесь , здесь и здесь ), и для каждого класса будут созданы новые соединения.

Если это так, настройте все так:

class LogDatabase < ActiveRecord::Base
  self.abstract_class = true
  establish_connection "log_database_#{Rails.env}".to_sym
end

class AccessLog < LogDatabase
end

class CheckoutLog < LogDatabase
end
18 голосов
/ 25 мая 2011

Подключение к различным базам данных довольно просто:

# model in the "default" database from database.yml
class Person < ActiveRecord::Base

  # ... your stuff here

end

# model in a different database
class Place < ActiveRecord::Base

  establish_connection (
    :adapter  => "mysql",
    :host     => "other_host",
    :username => "username",
    :password => "password",
    :database => "other_db"
  )

end

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

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

Объединение БД в одну не вариант? Это сделало бы вашу жизнь намного проще!

11 голосов
/ 14 июля 2012

Нашел отличный пост, который укажет другим на правильный способ сделать эту проверку http://blog.bitmelt.com/2008/10/connecting-to-multiple-database-in-ruby.html

Настройте что-то вроде этого:

database.yml (файл конфигурации БД)

support_development:
    adapter: blah
    database: blah
    username: blah
    password: blah

support_base.rb (файл модели)

class SupportBase < ActiveRecord::Base
    self.abstract_class = true #important!
    establish_connection("support_development")
end

tst_test.rb (файл модели)

class TstTest < SupportBase 
    #SupportBase not ActiveRecord is important!

    self.table_name = 'tst_test'

    def self.get_test_name(id)
        if id = nil
            return ''
        else
            query = "select tst_name from tst_test where tst_id = \'#{id}\'"
            tst = connection.select_all(query) #select_all is important!
            return tst[0].fetch('tst_name')
        end
    end
end

PS, это на самом деле не распространяется на миграцию, я не думаю, что вы можете выполнить миграцию на более чем одной БД с помощью rake (хотя я не уверен, что это сложная задача 'не может быть', возможно , Это был просто отличный способ подключиться и запросить другие БД, которые вы не контролируете.

5 голосов
/ 16 мая 2012

Возможно, вы захотите добавить среду Rails, чтобы ваши базы данных для разработки и тестирования не совпадали.

establish_connection "legacy_#{Rails.env}"
3 голосов
/ 17 июня 2015

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

Он также определяет знакомый db:migrate, который вызывает две другие задачи.

Включая здесь, когда ссылка становится недоступной:

desc "Migrate the database through scripts in db/migrate directory."

namespace :db do
  task :migrate do
    Rake::Task["db:migrate_db1"].invoke
    Rake::Task["db:migrate_db2"].invoke
  end

  task :migrate_db1 do
    ActiveRecord::Base.establish_connection DB1_CONF
    ActiveRecord::Migrator.migrate("db/migrate/db1/")
  end

  task :migrate_db2 do
    ActiveRecord::Base.establish_connection DB2_CONF
    ActiveRecord::Migrator.migrate("db/migrate/db2/")
  end
end

Источник: Ruby on Rails Подключение к нескольким базам данных и миграциям

1 голос
/ 14 мая 2013

Эй, этот пост старый, но я нашел решение, работающее на Rails 3.2, которое может помочь кому-то еще. https://stackoverflow.com/a/16542724/1447654

...