Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails migrations—temporarily ignore foreign key constraint?

I'm trying to change a table's id field to be a uuid

Here's my code:

class AddUuidToProjects < ActiveRecord::Migration[5.0]
  def up
    add_column :projects, :uuid, :string, limit:36, null: false, first: true
    add_column :projects, :old_id, :integer

    Project.all.each do |p|
      p.update!(old_id: p.id)
    end
    change_table :projects do |t|
      t.remove :id
      t.rename :uuid, :id
    end
    execute "ALTER TABLE projects ADD PRIMARY KEY (id);"

    Project.all.each do |p|
      # has_one image
      Image.find(p.old_id).update!(project: p) 
      # has_many stories
      Story.where(project_id: p.old_id).each do |s|
        s.update!(project: p)
      end
    end
  end
  ...
end

This migration breaks when trying t.remove :id, because of a foreign key constraint. The error message is:

Mysql2::Error: Cannot drop column 'id': needed in a foreign key constraint 'fk_rails_be41fd4bb7' of table 'db_dev.stories': ALTER TABLE `projects` DROP `id`

The thing is, if the whole migration ran then I would be swapping the id column out with another one, and fixing up the foreign keys too. So, is there any way to ignore the constraints for the migration?

like image 560
Mirror318 Avatar asked Oct 28 '25 16:10

Mirror318


2 Answers

Project.connection.disable_referential_integrity do
  Project.delete_all
end

ActiveRecord::Base.connection.disable_referential_integrity.

Rails 4.2+.

like image 174
Artur Beljajev Avatar answered Oct 31 '25 05:10

Artur Beljajev


On mysql, you can do this :

begin
  ActiveRecord::Base.connection.execute 'SET FOREIGN_KEY_CHECKS=0;'
  # Your statements
  ...
ensure
  ActiveRecord::Base.connection.execute 'SET FOREIGN_KEY_CHECKS=1;'
end
like image 36
Benj Avatar answered Oct 31 '25 06:10

Benj



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!