Rails: Adding an index after adding column

Ruby on-RailsIndexingMigration

Ruby on-Rails Problem Overview


Suppose I created a table table in a Rails app. Some time later, I add a column running:

rails generate migration AddUser_idColumnToTable user_id:string. 

Then I realize I need to add user_id as an index. I know about the add_index method, but where should this method be called? Am I supposed to run a migration (if yes, which one ?), then adding by hand this method?

Ruby on-Rails Solutions


Solution 1 - Ruby on-Rails

You can run another migration, just for the index:

class AddIndexToTable < ActiveRecord::Migration
  def change
    add_index :table, :user_id
  end
end

Solution 2 - Ruby on-Rails

If you need to create a user_id then it would be a reasonable assumption that you are referencing a user table. In which case the migration shall be:

rails generate migration AddUserRefToProducts user:references

This command will generate the following migration:

class AddUserRefToProducts < ActiveRecord::Migration
  def change
    add_reference :user, :product, index: true
  end
end

After running rake db:migrate both a user_id column and an index will be added to the products table.

In case you just need to add an index to an existing column, e.g. name of a user table, the following technique may be helpful:

rails generate migration AddIndexToUsers name:string:index will generate the following migration:

class AddIndexToUsers < ActiveRecord::Migration
  def change
    add_column :users, :name, :string
    add_index :users, :name
  end
end

Delete add_column line and run the migration.

In the case described you could have issued rails generate migration AddIndexIdToTable index_id:integer:index command and then delete add_column line from the generated migration. But I'd rather recommended to undo the initial migration and add reference instead:

rails generate migration RemoveUserIdFromProducts user_id:integer
rails generate migration AddUserRefToProducts user:references

Solution 3 - Ruby on-Rails

Add in the generated migration after creating the column the following (example)

add_index :photographers, :email, :unique => true

Solution 4 - Ruby on-Rails

For references you can call

rails generate migration AddUserIdColumnToTable user:references

If in the future you need to add a general index you can launch this

rails g migration AddOrdinationNumberToTable ordination_number:integer:index

Generated code:

class AddOrdinationNumberToTable < ActiveRecord::Migration
  def change
   add_column :tables, :ordination_number, :integer
   add_index :tables, :ordination_number, unique: true
  end
end

Solution 5 - Ruby on-Rails

You can use this, just think Job is the name of the model to which you are adding index cader_id:

class AddCaderIdToJob < ActiveRecord::Migration[5.2]
  def change
    change_table :jobs do |t|
      t.integer :cader_id
      t.index :cader_id
    end
  end
end

Solution 6 - Ruby on-Rails

For those who are using postgresql db and facing error

StandardError: An error has occurred, this and all later migrations canceled:

=== Dangerous operation detected #strong_migrations ===

Adding an index non-concurrently blocks writes

please refer this article

example:

class AddAncestryToWasteCodes < ActiveRecord::Migration[6.0]
  disable_ddl_transaction!

  def change
    add_column :waste_codes, :ancestry, :string
    add_index :waste_codes, :ancestry, algorithm: :concurrently
  end
end

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser1611830View Question on Stackoverflow
Solution 1 - Ruby on-RailsJaap HaagmansView Answer on Stackoverflow
Solution 2 - Ruby on-RailsVadym TyemirovView Answer on Stackoverflow
Solution 3 - Ruby on-RailsrdeandradeView Answer on Stackoverflow
Solution 4 - Ruby on-RailsMauroView Answer on Stackoverflow
Solution 5 - Ruby on-Railsvidur punjView Answer on Stackoverflow
Solution 6 - Ruby on-RailstheabhisheksoniView Answer on Stackoverflow