Rails 6.1 adds `if_exists` option in `remove_index` operation


In few applications, we have migrations to remove index where we don’t want to raise an error if an index was already removed.

Rails 6.1 adds a feature, where we can now pass if_exists option to remove_index operation. This is similar to if_not_exists option when we are adding an index on table.

Before

Let’s say we have a comments table with description, post_id and user_id as columns. We add a data migration to remove the index on the description column. If this index was already removed the data migration will throw an error as below.

class RemoveDescriptionIndexOnComments < ActiveRecord::Migration[6.0]
  def change
    remove_index :comments, :description
  end
end

rails db:migrate

== 20210320151534 RemoveDescriptionIndexOnComments: migrating ===========================
-- remove_index(:comments, :description)
rails aborted!
StandardError: An error has occurred, this and all later migrations canceled:

No indexes found on comments with the options provided.

After

After the changes in Rails 6.1, the above migration will not raise any error if we pass if_exists as true.

class RemoveDescriptionIndexOnComments < ActiveRecord::Migration[6.1]
  def change
    remove_index :comments, :description, if_exists: true
  end
end

rails db:migrate

== 20210320151534 RemoveDescriptionIndexOnComments: migrating ===========================
-- remove_index(:comments, :description, {:if_exists=>true})
   -> 0.0033s
== 20210320151534 RemoveDescriptionIndexOnComments: migrated (0.0034s) ==================

Rails does not execute any SQL query for DROP INDEX in the above case.