Say, we have something like this:

add_column :users, :single, :boolean
add_index :users, :single

and then later we do

rename_column :users, :single, :married

Will ActiveRecord and/or the database handle the renaming of the index as well or do I have to manually drop the index and add it again?


For PostgreSQL, rename_column is implemented as a simple ALTER TABLE ... RENAME COLUMN ... and that does preserve the indexes.

The MySQL versions (both of them) do an ALTER TABLE ... CHANGE ... and that also preserves the indexes.

The SQLite version appears to copy the entire table (with indexes), drop the old one, and then copy the copy back to the original table name. The copying does appear to handle the column rename while copying the indexes:

def copy_table(from, to, options = {})
  #...
  copy_table_indexes(from, to, options[:rename] || {})

and inside copy_table_indexes:

columns = index.columns.map {|c| rename[c] || c }.select do |column|
  to_column_names.include?(column)
end

So, the standard drivers will preserve your indexes when you do a rename_column and the SQLite driver goes to some effort to do so.

The API documentation doesn't specify any particular behavior though so other drivers may do other things. The closest the documentation comes to saying anything about indexes is this in active_record/migration.rb:

rename_column(table_name, column_name, new_column_name): Renames a column but keeps the type and content.

I think any driver would preserve the indexes but there's no guarantee; a driver writer would certainly be foolish not to preserve the indexes.

This isn't a definitive or authoritative answer but your indexes should be preserved if you use the standard PostgreSQL, MySQL (either one of them), or SQLite drivers.


Note that even though the index itself survives the column renaming there's no guarantee that the index name will be changed. This shouldn't be a problem unless you're doing something (such as manually dropping it) that cares about the index name rather than what columns are involved.

The above behavior changed in Rails 4:

  • In Rails 4.0 when a column or a table is renamed the related indexes are also renamed. If you have migrations which rename the indexes, they are no longer needed.

So ActiveRecord will automatically rename indexes to match the new table or column names when you rename the table or column. Thanks to sequielo for the heads-up on this.