ActiveRecord与两个数据库交谈?

Mik*_*cic 15 ruby database activerecord ruby-on-rails

我们最近修改了一个项目,并希望将所有旧数据引入新系统.问题是模式略有不同,因此无法进行直接的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
Run Code Online (Sandbox Code Playgroud)

在上面的示例中,OldUser正在从旧数据库中读取,NewUser正在处理新数据库.我需要两组模型(新旧)来保持它们的关联,以正确地对一些数据进行非规范化.

有没有可以帮我这样做的项目/图书馆?

Fra*_*eil 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
Run Code Online (Sandbox Code Playgroud)

从常规代码中,您可以像以前一样使用模型:

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

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
Run Code Online (Sandbox Code Playgroud)

注意命名约定 - 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
Run Code Online (Sandbox Code Playgroud)

宾果,其他一切都会好起来的.

  • 请注意,`set_table_name`已被删除,以支持`self.table_name`. (2认同)

Jed*_*der 5

更新了一个扩展示例,该示例显示了表上的外键,还有几个示例显示了如何识别没有标准列名以正确地在rails中进行路由。

在您的应用程序中

models
  |_ legacy
     |_ base.rb
     |_ user.rb
     |_ company.rb
  |_ user.rb
Run Code Online (Sandbox Code Playgroud)

班级代码

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
Run Code Online (Sandbox Code Playgroud)

并根据需要调整范围

Legacy::User.new
User.new

Legacy::User.first.companies #=> returns array of Legacy::Companies
Run Code Online (Sandbox Code Playgroud)