38

I created a table using the following migration:

class CreateProfilePictures < ActiveRecord::Migration
  def change
    create_table :profile_pictures do |t|
      t.integer :user_id, null: false
      t.integer :picture_id, null: false
      t.timestamps null: false
    end

    add_index :profile_pictures, :user_id, unique: true
    add_index :profile_pictures, :picture_id, unique: true
  end
end

I tried to remove the constraint with the following:

class FixProfilePic < ActiveRecord::Migration
  def change
    change_column :profile_pictures, :picture_id, :integer, unique: false
  end
end

I still get a unique constraint violation error if I try to use the same picture_id in more than one place. What is the proper way to remove the uniqueness constraint from picture_id?

1
  • You need to remove the index. Commented Nov 3, 2015 at 9:38

4 Answers 4

70

You must remove your index with:

remove_index :profile_pictures, :picture_id

and add it again with:

add_index :profile_pictures, :picture_id

ActiveRecord::Migration

Sign up to request clarification or add additional context in comments.

2 Comments

This no longer works. What works now is: remove_index :profile_pictures, name: 'picture_id'
Beware, a rollback of this migration won't restore the UNIQUE constraint.
18

There is a problem with the accepted answer: Rollbacks don't work correctly as the unique index is not restored.

You could try this instead:

reversible do |dir|
  dir.up do
    remove_index :profile_pictures, :picture_id
    add_index :profile_pictures, :picture_id
  end

  dir.down do
    remove_index :profile_pictures, :picture_id
    add_index :profile_pictures, :picture_id, unique: true
  end
end

1 Comment

I've accepted this as the new answer
11

add_index :profile_pictures, :picture_id, unique: true

So update your index to:

  remove_index :profile_pictures, :picture_id
  add_index :profile_pictures, :picture_id

I'm guessing this is it.

Comments

2

For the migration to be reversible, you now (Rails 6+) need to use the :column option.

Adding unique: true also ensures rolling back the migration will recreate the index with the uniqueness constraint (barring problematic data being inserted in the meantime).

  remove_index :profile_pictures, column: :picture_id, unique: true
  add_index :profile_pictures, :picture_id

One more thing to note: if your table is large, then creating a new index on it could lock writes to it for a long time. Consider using algorithm: :concurrently if you use Postgres

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.