While working on a Rails app, we all have had to rename a column on a database using a migration. Yet, I’m always looking up how to do it, to be sure I’m not mistyping something. So here is the good way to do it in Rails 5, using rename_column. Don’t worry, you won’t loose any data in this column.
In this article, we will be covering different situations and identifying potential gotchas.
How to change a column name in a migration:
- Generate a migration in the console: rails g migration ChangeColumnName
- Go to the generated migration file and modify the
changemethod in this way:
rename_column :table_name, :old_column, :new_column
- Run rails db:migrate, and don’t forget to update your code with the new name.
Here is what the migration should look like for Rails 5:
Let’s say you have an “email” column on the “users” table, that you would like to change to “email_address”:
class ChangeColumnName < ActiveRecord::Migration[5.0] def change rename_column :users, :email, :email_address end end
Since Rails 4, the
down methods are not required anymore (but it would still be valid).
Be careful with the reserved names in Rails or SQL when you rename a column
Something to look out when you rename a column in Rails: the reserved names. You will run into troubles if you use them, sometimes not right away.
And there are a LOT of them. Therefore, you can’t rename your database column using ‘group’, ‘image’, ‘set’, ‘open’, etc.
Here is a resource where you can check if the name you want is reserved: Reserved words in Ruby on Rails.
Bonus: Change column type in Rails
In addition to renaming a column, you might be interested in how to change a column type. We will see that now.
For modifying the name, we used “rename_column”. In a similar way, we will use “change_column”
Let’s say you have a Projects table with a deadline column, of type “date”. You want to change it to a “datetime” type so you can store the time as well.
Using “change_column”, your migration will look like this:
change_column :projects, :deadline, :datetime
You can add several lines to this migration, should you need to modify different column names on different database tables.
But wait, what happens if I rollback?
The problem with “change_column” is that it is an irreversible migration. It will cause an error if you ever try to rollback.
To prevent this, modify the usual “change” method in the migration to use two separate up and down methods. The up method contains what you want to do, and the down method the opposite. Like this:
class ChangeDateColumnToDatetime < ActiveRecord::Migration[5.0] def up change_column :projects, :deadline, :datetime end def down change_column :projects, :deadline, :date end end
This effectively tells Rails what to do in event of a rollback.