假设您有“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,但我担心后备支持所以我只是在这里发布这个提示/建议/正确方向。
谢谢!
答案 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列。