Подключение Rails 3.1 с несколькими базами данных

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

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

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

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

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

Ответ 1

В ответ на 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

Ответ 2

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

# 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, поскольку вы добавили много накладных расходов на поиск данных для ваших контроллеров, что может замедлить работу.

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

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

Ответ 3

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

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

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

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, это действительно не распространяется на миграцию, я не думаю, что вы можете выполнять миграции более чем на одной БД с граблями (хотя я не уверен, что это трудно "не могу", возможно, это возможно), Это был просто отличный способ подключить и запросить другие БД, которые вы не контролируете.

Ответ 4

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

establish_connection "legacy_#{Rails.env}"

Ответ 5

следующая статья предлагает определить новые задачи 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 Подключение к нескольким базам данных и миграции

Ответ 6

Эй, этот пост старый, но я нашел решение, работающее над Rails 3.2, которое может помочь кому-то другому. fooobar.com/info/74323/...