ActiveRecord如何连接两个数据库?

15

我们最近重新设计了一个项目,现在想将所有旧数据导入到新系统中。问题在于,由于模式略有不同,无法直接进行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正在新数据库上工作。我需要保留两组模型(新和旧)的关联,以便正确地去规范化某些数据。是否有任何项目/库可以帮助我做到这一点?
3个回答

20

你应该在模型或database.yml中简单地指定连接选项。首先让我们走第一条路:

# 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文件中,并使用正确的establish_connection语法连接:

# 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

完美,其它所有东西都将正常工作。


2
请注意,set_table_name已被弃用,应使用self.table_name - Thomas Obermüller

5

更新了一个扩展示例,展示了表格上的外键以及几个例子,展示了如何正确识别非标准列名以在rails中正确路由。

在您的应用程序内部

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

这将如何与关联一起工作?假设我的用户拥有一个公司。如果我的 Legacy::User 有一个公司关联,它会默认使用 Legacy 模块中的那个,还是(错误地)与较新的公司模型相关联? - Mike Trpcic
你的表格和列名是什么?我会修改这个例子。 - Jed Schneider

2

你的选择有:

  • Magic Models 最后更新于2009年(截至2012年11月1日)

  • Connection Ninja 最后更新于2010年(截至2012年11月1日)

  • DB Charmer 最近更新约6个月前(截至2012年11月1日)

  • 在模型中覆盖establish_connection以连接到所需的数据库

  • Activewarehouse-etl - 一个相当活跃的gem,用于进行数据库抽取转换加载工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接