Łączenie Rails 3.1 z wieloma bazami danych

W ShowNearby wykonaliśmy bardzo dużą migrację do RoR 3.1 z PHP i mamy do czynienia z kilkoma problemami, które być może niektórzy z Was już rozwiązali.

Mamy duże ilości danych i postanowiliśmy podzielić nasze DB na kilka DB, które możemy obsłużyć osobno. Na przykład nasze konta, miejsca, dzienniki i inne są podzielone na kilka baz danych

Musimy zrobić migracje, oprawy, modele, aby grać ładnie, a do tej pory było dość niechlujnie. Niektóre z naszych wymagania dotyczące dopuszczalnego rozwiązania:

  • Jeden model powinien odnosić się do jednej tabeli w jednej z baz danych.
  • rake db : drop - powinien upuścić całą bazę danych ENV, którą podajemy w bazie danych.yml
  • rake db: create - należy utworzyć całą bazę danych ENV, którą podamy w bazie danych.yml
  • rake db: migrate-powinno uruchamiać migracje do różnych baz danych
  • rake db: test - należy chwycić uchwyty i wrzucić je do różnych baz danych i przetestować unit / function / etc

Rozważamy ustawienie oddzielnych projektów rails dla każdej bazy danych i połączenie ich z ActiveResource, ale uważamy, że nie jest to zbyt efektywne. Czy ktoś z Was miał wcześniej podobny problem?

Wielkie dzięki!!

Author: user2262149, 2011-05-25

6 answers

Aby uzyskać odpowiedź Wukerplank, możesz również umieścić szczegóły połączenia w bazie danych.yml jak zwykle z taką nazwą:

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

Następnie w Twoim specjalnym modelu:

class AccessLog < ActiveRecord::Base
  establish_connection "log_database_#{Rails.env}".to_sym
end
Żeby te brzydkie poświadczenia nie znalazły się w Twoim kodzie aplikacyjnym.

Edit: Jeśli chcesz ponownie użyć tego połączenia w wielu modelach, powinieneś utworzyć nową abstrakcyjną klasę i dziedziczyć z niej, ponieważ połączenia są ściśle powiązane z klasami (jak wyjaśniono tutaj, tutaj , i tutaj ), a nowe połączenia będą tworzone dla każdej klasy.

Jeśli tak jest, Ustaw rzeczy tak:

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
 141
Author: Unixmonkey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-14 15:47:01

Łączenie się z różnymi bazami danych jest dość łatwe:

# 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

Byłbym ostrożny w konfigurowaniu wielu projektów Rails, ponieważ dodasz wiele narzutu do pobierania danych dla swoich kontrolerów, co może spowolnić działanie.

Jeśli chodzi o Twoje pytania dotyczące migracji, osprzętu, modeli itp.: Myślę, że nie będzie łatwego sposobu, więc proszę pisać osobne pytania i być jak najbardziej szczegółowym.

Konsolidacja DBs w jeden nie wchodzi w grę? To uczyniłoby twoje życie dużo łatwiej!

 18
Author: Wukerplank,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-25 10:06:06

Znalazłem świetny post, który wskaże innym właściwy sposób zrobienia tego Sprawdź http://blog.bitmelt.com/2008/10/connecting-to-multiple-database-in-ruby.html

Ustaw coś takiego:

Baza Danych.yml (plik konfiguracyjny db)

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

Support_base.rb (plik modelu)

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

Tst_test.rb (plik modelu)

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, to naprawdę nie obejmuje migracji, nie sądzę, że można zrobić migracje na więcej niż jeden DB z rake (chociaż nie jestem oczywiście, że jest to trudne "nie można", to może być możliwe). To był po prostu świetny sposób na łączenie się i odpytywanie innych DBs, których nie kontrolujesz.

 11
Author: TwoByteHero,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-28 00:34:39

Możesz również dodać środowisko Rails, więc Twoje bazy danych programistycznych i testowych nie są takie same.

establish_connection "legacy_#{Rails.env}"
 4
Author: Kris,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-16 13:18:50

Następujący artykuł sugeruje zdefiniowanie nowych zadań Rake w celu uzyskania migracji z wielu baz danych. Każde zadanie tworzy własne połączenie, a następnie wykonuje migrację z tym połączeniem i określonym folderem bazy danych.

Definiuje również znane db:migrate, które wywołuje dwa pozostałe zadania.

W tym miejscu link staje się niedostępny:

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

Źródło: Ruby on Rails łączy się z wieloma bazami danych i migracjami

 3
Author: cweston,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-17 14:30:45

Hej ten post jest stary, ale znalazłem rozwiązanie działające na Rails 3.2, które może komuś pomóc. https://stackoverflow.com/a/16542724/1447654

 1
Author: Rafael,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:25:34