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 

這就是說,如果有更好或更習慣的方法來解決這個問題,