ActiveRecord говори с две бази данни?

Наскоро обновихме проект и се стремим да пренесем всички наши стари данни в новата система. Проблемът е, че схемата е малко по-различна, така че директно импортиране на SQL не е възможно. Поради известна денормализация и промени в базата данни, ще трябва да направим известно масажиране на данните, преди да са готови за импортиране. Надявах се на нещо подобно:

OldUser.all.each do |ou|
  NewUser.create({
    :first_name   => ou.first_name
    :last_name    => ou.last_name
    :login        => ou.login
    :company_name => ou.company.name
  })
end

В горния пример OldUser чете от старата база данни, а NewUser работи върху новата база данни. Имам нужда от двата набора от модели (нов и стар), за да запазя асоциациите си, за да денормализирам правилно част от тези данни.

Има ли някакъв проект/библиотека, който може да ми помогне да направя това?


person Mike Trpcic    schedule 31.08.2010    source източник


Отговори (3)


Трябва просто да посочите вашите опции за връзка или в модела, или в database.yml. Първоначално да минем по 1-вия маршрут:

# This is the new users table - connects to development/test/production
# DB from database.yml
class User < ActiveRecord::Base
end

class OldUser < ActiveRecord::Base
  establish_connection :adapter  => "postgresql",
                       :database => "legacy_users",
                       :username => "whatever",
                       :password => "something"
  set_table_name "u_users" # Whatever you require
  belongs_to :company, :class_name => "OldCompany", :foreign_key => "fk_company_id"
end

class OldCompany < ActiveRecord::Base
  establish_connection :adapter  => "postgresql",
                       :database => "legacy_users",
                       :username => "whatever",
                       :password => "something"
  set_table_name "u_company" # Whatever you require
  has_many :users, :class_name => "OldUser", :foreign_key => "fk_company_id"
end

От обикновения код използвате моделите, както сте свикнали:

OldUser.find_each do |ouser|
  User.create!(:username => ouser.username, :company_name => ouser.company.name)
end

ActiveRecord ще се справи с всички подробности вместо вас.

Сега, ако сте като мен, не ви харесва да поставяте такова ниво на подробности във вашите модели - потребителско име, пароли и т.н. Лесно - преместете тази конфигурация в database.yml и се свържете, като използвате правилния синтаксис установяване на връзка:

# database.yml
development:
  adapter: postgresql
  # go on as usual, for all 3 envs

legacy_users_development:
  adapter:  postgresql
  database: legacy_users
  username: whatever
  password: something

Обърнете внимание на конвенцията за именуване - legacy_users_#{Rails.env} е това, към което се стремя тук, и ето как да го направя:

class OldUser < ActiveRecord::Base
  establish_connection "legacy_users_#{Rails.env}"
  set_table_name "u_users" # Whatever you require
  belongs_to :company, :class_name => "OldCompany", :foreign_key => "fk_company_id"
end

Бинго, всичко останало ще работи добре.

person François Beausoleil    schedule 31.08.2010
comment
Моля, имайте предвид, че set_table_name беше премахнат в полза на self.table_name. - person Thomas Obermüller; 21.08.2014

АКТУАЛИЗИРАН с разширен пример, показващ чужди ключове на таблиците и няколко примера, показващи как да се идентифицират нестандартни имена на колони, за да се маршрутизира правилно в релси.

във вашето приложение

models
  |_ legacy
     |_ base.rb
     |_ user.rb
     |_ company.rb
  |_ user.rb

код на класа

module Legacy
  class Base < ActiveRecord::Base
    self.abstract_class :true
    establish_connection "database here"
  end
end

module Legacy
  class User < Legacy::Base
    :has_many :companies, :class_name => 'Legacy::Company', :foreign_key => 'user_id'
  end
end

module Legacy
  class Company < Legacy::Base
    set_table_name 'companies'
    set_primary_key 'someId'
    belongs_to :user, :class_name => 'Legacy::User', :foreign_key => 'operator'
  end
end

и го обхванете там, където имате нужда

Legacy::User.new
User.new

Legacy::User.first.companies #=> returns array of Legacy::Companies
person Jed Schneider    schedule 31.08.2010
comment
Как ще стане това с асоциациите. Да кажем, че моят потребител има фирма. Ако моят Legacy::User има асоциация към фирма, ще бъде ли по подразбиране тази в модула Legacy или (погрешно) ще се асоциира с по-новия модел на фирма? - person Mike Trpcic; 31.08.2010
comment
какво е името на вашата таблица и колона и ще променя примера - person Jed Schneider; 31.08.2010

Вашите опции са:

  • Magic Models Последна актуализация през 2009 г. (към 1.11.2012 г.)

  • Connection Ninja Последна актуализация през 2010 г. (към 1.11.2012 г.)

  • DB Charmer Последна актуализация приблизително 6 месеца преди (към 1.11.2012 г.)

  • Замяна на establish_connection във вашия модел, за да се свържете с желаната база данни

  • Activewarehouse-etl - доста активен скъпоценен камък за извършване на db Extract Transform Load работа.

person Sam Saffron    schedule 31.08.2010