Rails: How can I rename a database column in a Ruby on Rails migration? Rails: How can I rename a database column in a Ruby on Rails migration? ruby-on-rails ruby-on-rails

Rails: How can I rename a database column in a Ruby on Rails migration?


rename_column :table, :old_column, :new_column

You'll probably want to create a separate migration to do this. (Rename FixColumnName as you will.):

script/generate migration FixColumnName# creates  db/migrate/xxxxxxxxxx_fix_column_name.rb

Then edit the migration to do your will:

# db/migrate/xxxxxxxxxx_fix_column_name.rbclass FixColumnName < ActiveRecord::Migration  def self.up    rename_column :table_name, :old_column, :new_column  end  def self.down    # rename back if you need or do something else or do nothing  endend

For Rails 3.1 use:

While, the up and down methods still apply, Rails 3.1 receives a change method that "knows how to migrate your database and reverse it when the migration is rolled back without the need to write a separate down method".

See "Active Record Migrations" for more information.

rails g migration FixColumnNameclass FixColumnName < ActiveRecord::Migration  def change    rename_column :table_name, :old_column, :new_column  endend

If you happen to have a whole bunch of columns to rename, or something that would have required repeating the table name over and over again:

rename_column :table_name, :old_column1, :new_column1rename_column :table_name, :old_column2, :new_column2...

You could use change_table to keep things a little neater:

class FixColumnNames < ActiveRecord::Migration  def change    change_table :table_name do |t|      t.rename :old_column1, :new_column1      t.rename :old_column2, :new_column2      ...    end  endend

Then just db:migrate as usual or however you go about your business.


For Rails 4:

While creating a Migration for renaming a column, Rails 4 generates a change method instead of up and down as mentioned in the above section. The generated change method is:

$ > rails g migration ChangeColumnName

which will create a migration file similar to:

class ChangeColumnName < ActiveRecord::Migration  def change    rename_column :table_name, :old_column, :new_column  endend


In my opinion, in this case, it's better to use rake db:rollback, then edit your migration and again run rake db:migrate.

However, if you have data in the column you don't want to lose, then use rename_column.


If the column is already populated with data and live in production, I'd recommend a step by step approach, so as to avoid downtime in production while waiting for the migrations.

First I'd create a db migration to add columns with the new name(s) and populate them with the values from the old column name.

class AddCorrectColumnNames < ActiveRecord::Migration  def up    add_column :table, :correct_name_column_one, :string    add_column :table, :correct_name_column_two, :string    puts 'Updating correctly named columns'    execute "UPDATE table_name SET correct_name_column_one = old_name_column_one, correct_name_column_two = old_name_column_two"    end  end  def down    remove_column :table, :correct_name_column_one    remove_column :table, :correct_name_column_two  endend

Then I'd commit just that change, and push the change into production.

git commit -m 'adding columns with correct name'

Then once the commit has been pushed into production, I'd run.

Production $ bundle exec rake db:migrate

Then I'd update all of the views/controllers that referenced the old column name to the new column name. Run through my test suite, and commit just those changes. (After making sure it was working locally and passing all tests first!)

git commit -m 'using correct column name instead of old stinky bad column name'

Then I'd push that commit to production.

At this point you can remove the original column without worrying about any sort of downtime associated with the migration itself.

class RemoveBadColumnNames < ActiveRecord::Migration  def up    remove_column :table, :old_name_column_one    remove_column :table, :old_name_column_two  end  def down    add_column :table, :old_name_column_one, :string    add_column :table, :old_name_column_two, :string  endend

Then push this latest migration to production and run bundle exec rake db:migrate in the background.

I realize this is a bit more involved of a process, but I'd rather do this than have issues with my production migration.