0

我正在尝试使用Rails中的Active Record迁移将列添加到现有表中。我需要列的初始值基于表中的其他列。有没有办法在Active Record迁移中做到这一点?在基于其他列的初始值中添加Rails Active Record迁移中的列

为了使它更具体,让我们说我有以下几点:

my_table 
---------------- 
first_name: text 
last_name: text 

我想用concat(first_name, ' ', last_name'初始值增加full_name文本列。请注意,我不希望列上有一个默认值,因为我打算让应用程序向前填充(初始默认值只是为现有记录创建一个合理的起始值)。

如何在迁移中执行此操作?理想情况下,我想使用add_column或类似的,但如果这不能工作,一个可行的替代方案将是可以接受的。

请注意,已经存在一个几乎相同的问题(add a database column with Rails migration and populate it based on another column),但它的答案似乎没有一个完全回答这个问题。

+0

我的方法不行吗? –

+0

@DanilSperansky它的确如此,但是当模型在迁移过程中超过这一点时,它可能会受到问题的影响(在其他答案中指出),这就是为什么我将SQL解决方案发布到更新中的原因。因为它不会尝试实例化活动记录对象,所以我可以想到的唯一一个角落案例就是如果在之后有一个迁移重命名或删除表的话。 –

回答

1

您可以在add_column之后使用update_all。对于MySQL:

Person.update_all('full_name = concat(first_name, " ", last_name)') 
+0

根据我对这个问题本身的评论,我会想象如果随后的迁移删除或重命名此表,这将失败,因为具有该名称的活动记录对象将不再存在以调用'update_all'。换句话说,它不是完全面向未来的。 –

1

我结束了使用add_column,然后使用直接SQL更新列的值加上列。我使用的是直接SQL,而不是根据this answer的模型,因为它不依赖于模型的当前状态与基于正在运行的迁移的表的当前状态。

class AddFullName < ActiveRecord::Migration 
    def up 
    add_column :my_table, :full_name, :text 
    execute "update my_table set full_name = concat(first_name, ' ', last_name)" 
    end 

    def down 
    remove_column :my_table, :full_name 
    end 
end 

这就是说,如果有更好或更习惯的方法来解决这个问题,