How to create a migration to remove an index only if it exists, rather than throwing an exception if it doesn't?

rails-migrations, ruby-on-rails, ruby-on-rails-4

Solution

You can use the `index_exists?` method within your migration to test whether the index you need to remove is actually there.

Take a look at the documentation here: http://apidock.com/rails/ActiveRecord/ConnectionAdapters/SchemaStatements/index_exists%3F

I've not tested it, but you should be able to use something like this:

class AddTimestampIndexes < ActiveRecord::Migration
  def up
    remove_index :books, :created_at if index_exists?(:books, :created_at)
    remove_index :books, :updated_at if index_exists?(:books, :updated_at)

    add_index  :books, :created_at
    add_index  :books, :updated_at
  end

  def down
    remove_index :books, :created_at
    remove_index :books, :updated_at
  end
end

Although, by the looks of things, you really only want to create them if they don't exist? This might be more appropriate for your migration:

class AddTimestampIndexes < ActiveRecord::Migration
  def up
    add_index  :books, :created_at unless index_exists?(:books, :created_at)
    add_index  :books, :updated_at unless index_exists?(:books, :updated_at)
  end

  def down
    remove_index :books, :created_at
    remove_index :books, :updated_at
  end
end

Problem

Right now, the current migration might fail, if the `books` table doesn't have `created_at` or `updated_at` fields: ``` class AddTimestampIndexes < ActiveRecord::Migration def up remove_index :books, :created_at remove_index :books, :updated_at add_index :books, :created_at add_index :books, :updated_at end def down remove_index :books, :created_at remove_index :books, :updated_at end end ``` Does `remove_index` take any options to silently proceed if it fails to remove the index rather than raising an error?

Original source