在Rails迁移中迁移数据

时间:2009-12-11 01:14:44

标签: ruby-on-rails migration

假设您有“lineitems”并且您曾经使用line_item来定义“make”。

最终你意识到make应该在它自己的模型上,所以你创建了一个Make模型。

然后,您想要删除line_items表中的make列,但是对于每个带有make的line_item,您想要find_or_create_by(line_item.make)。

如何在rails迁移中有效地执行此操作?我很确定我可以为每个line_item运行一些简单的find_or_create_by,但我担心后备支持所以我只是在这里发布这个提示/建议/正确方向。

谢谢!

2 个答案:

答案 0 :(得分:3)

我猜你应该在删除列之前检查Make.count是否等于lineitems中的唯一make总数,如果没有则会引发错误。由于迁移是事务性的,如果它发生爆炸,则不会更改架构,并且迁移不会标记为已执行。因此,您可以这样做:

class CreateMakesAndMigrateFromLineItems < ActiveRecord::Migration
  def self.up
    create_table :makes do |t|
      t.string :name
      …
      t.timestamps
    end

    makes = LineItem.all.collect(:&make).uniq
    makes.each { |make| Make.find_or_create_by_name make }
    Make.count == makes.length ? remove_column(:line_items, :make) : raise "Boom!"

  end

  def self.down
    # You'll want to put logic here to take you back to how things were before. Just in case!
    drop_table :makes
    add_column :line_items, :make
  end
end

答案 1 :(得分:0)

您可以在迁移中放置常规ruby代码,这样您就可以创建新表,在旧模型上运行一些代码,将数据移动到新模型中,然后从原始模型中删除列。这甚至是可逆的,因此您的迁移仍然可以在两个方向上进行。

因此,根据您的情况,创建Make表并向lineitem添加make_id。然后,对于每个订单项{4},使用lineitem上的make列,将返回的ID设置为lineitem上的新make_id。完成后,从lineitem表中删除旧的make列。