Reputation: 21189
I am attempting to add a column to an existing table using an Active Record migration in Rails. I need the column's initial value to be based on other columns in the table. Is there a way to do this in an Active Record migration?
To make it more concrete, let's say I have the following:
my_table
----------------
first_name: text
last_name: text
I want to add a full_name
text column with an initial value of concat(first_name, ' ', last_name'
. Note that I don't want a default value on the column, as I intend for the application to be populating this going forward (the initial default is just to have a sensible starting value for existing records).
How can I do this in a migration? Ideally I would like to use add_column
or similar, though if that can't work a working alternative would be acceptable.
Note that there already exists a nearly identical question (add a database column with Rails migration and populate it based on another column), but none of its answers seem to fully answer this question.
Upvotes: 1
Views: 2315
Reputation: 21189
I ended up adding the column using add_column
and then using direct SQL to update the value of the column. I used direct SQL and not the model per this answer, since then it doesn't depend on the current state of the model vs. the current state of the table based on migrations being run.
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
That said, if there is a better or more idiomatic approach to this, I'm all ears.
Upvotes: 1
Reputation: 30463
You could use update_all
after add_column
. For MySQL:
Person.update_all('full_name = concat(first_name, " ", last_name)')
Upvotes: 2