将旧数据迁移到 Rails 中的新模型

Chr*_*ngs 3 ruby database postgresql ruby-on-rails ruby-on-rails-4

我再次开始使用 Rails,但遇到了一个令我感到害怕的难题。在使用数据库方面我有点菜鸟,所以如果这是相当基础的,请原谅我。

\n\n

我有一个较旧的 Rails 应用程序,其中包含我不再希望遵循的数据模型。应弃用该模型,转而采用更轻、更简单的模型。

\n\n

旧的应用程序也非常单一,因此我尝试将其分解为更小的服务组件。

\n\n

因此,这引出了我的问题,因为通常不赞成使用单个模型\xe2\x80\xa6 中的多个数据库,将旧模型中存储的数据转换为新模型的最佳方法是什么?一次服务?

\n\n

例如,假设我有一个新旧用户模型。在旧模型中,用户有很多列,但并非所有列都应该进入新模型。

\n\n

例如,用户从旧模型中仅限于单个地址,变为能够分配一对多关系,其中地址在自己的模型中分开,并使用外键或其他内容简单地引用。

\n\n

编辑1:

\n\n

最终目标是尽可能轻松地将数据从旧模型的数据库转移到新模型的数据库中,一次一个数据集。

\n\n

编辑2:

\n\n

最初是从我的手机发布的。以下是一些可能有助于提供建议的示例。

\n\n

旧型号

\n\n
  create_table "brands", force: :cascade do |t|\n    t.string   "name"\n    t.string   "url"\n    t.string   "logo"\n    t.boolean  "verified"\n    t.datetime "created_at",                                   null: false\n    t.datetime "updated_at",                                   null: false\n    t.boolean  "hidden",                       default: false\n    t.string   "facebook_url"\n    t.string   "twitter_handle"\n    t.string   "pinterest_handle"\n    t.string   "google_plus_url"\n    t.string   "address_street1"\n    t.string   "address_street2"\n    t.string   "address_street3"\n    t.string   "address_city"\n    t.string   "address_state"\n    t.string   "address_zip"\n    t.string   "address_country"\n    t.string   "email"\n    t.string   "phone"\n    t.string   "story_title"\n    t.text     "story_text"\n    t.string   "story_photo"\n  end\n
Run Code Online (Sandbox Code Playgroud)\n\n

新模型

\n\n
  create_table "companies", force: :cascade do |t|\n    t.string   "companyName",                               null: false\n    t.string   "companyURL",                                null: false\n    t.boolean  "companyIsActive",                 default: true,   null: false\n    t.boolean  "companyDataIsVerified",           default: false,  null: false\n    t.string   "companyLogoFileURL"\n    t.datetime "companyFoundedOnDate"\n    t.integer  "companyHQLocationID"\n    t.integer  "companyParentCompanyID"\n    t.integer  "companyFirstSuggestedByID"\n    t.string   "companyFacebookURL"\n    t.string   "companyGooglePlusURL"\n    t.string   "companyInstagramURL"\n    t.string   "companyPinterestURL"\n    t.string   "companyTwitterURL"\n    t.string   "companyStoryTitle"\n    t.text     "companyStoryContent"\n    t.string   "companyStoryImageFileURL"\n    t.boolean  "companyIsHiddenFromIndex",        default: false, null: false\n    t.integer  "companyDataScraperID"\n    t.datetime "created_at",                                null: false\n    t.datetime "updated_at",                                null: false\n  end\n
Run Code Online (Sandbox Code Playgroud)\n\n

所以,基本上......我希望能够从旧模型中获取数据,比如说一个品牌“名称”列,并将其相关值转移到新模型中,这样该值最终会出现在一个完全的公司“companyName”列中不同的 postgresql 实例。

\n

Kar*_*bur 5

多次执行此操作后,我可以告诉您,最简单的方法是创建一个简单的 rake 任务,该任务迭代第一个集合并在新集合中创建项目。

不需要使用DataMapper之类的东西。您已经拥有 ActiveRecord,并且可以简单地定义每个模型使用哪个数据库连接。

在你的config/database.yml

brand_database:
  adapter: postgresql
  host: brand_host
  username: brand_user
  password: brand_pass
  database: brand_db

company_database:
  adapter: postgresql
  host: company_host
  username: company_user
  password: company_pass
  database: company_db
Run Code Online (Sandbox Code Playgroud)

在你的模型中:

class Brand < ActiveRecord::Base
  establish_connection :brand_database
end

class Company < ActiveRecord::Base
  establish_connection :company_database
end
Run Code Online (Sandbox Code Playgroud)

在您的新 rake 任务 ( lib/tasks/db.rake) 中:

# lib/tasks/db.rake
namespace :db do
  desc "Migrate brand records to company records"
  task :migrate_brands_to_companies, [] => :environment do
    Brand.find_each do |brand|
      Company.find_or_initialize_by(companyName: brand.name) do |company|
        puts "\n\tCreating Company record for #{brand.name}"
        company.companyURL               = brand.url
        company.companyLogoFileURL       = brand.logo
        company.companyTwitterURL        = "https://twitter.com/#{brand.twitter_handle}"
        company.companyIsHiddenFromIndex = brand.hidden
        company.created_at               = brand.created_at
        company.updated_at               = brand.updated_at
        company.save!
      end
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

最后,运行 rake 任务:

$ rake db:migrate_brands_to_companies
Run Code Online (Sandbox Code Playgroud)

我需要这样说:Rails 是使用可靠的约定构建的。不遵守该约定每次都会导致问题和额外费用。我已经见过很多次了。每当我看到有人偏离这个惯例时,他们就会遇到比他们预想的更多的麻烦。他们打破了很多“Rails 魔法”。