1

Я пытаюсь изменить id поле за столом, чтобы быть uuidRails migrations - временно игнорировать ограничение внешнего ключа?

Вот мой код:

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 

Эта миграция ломается при попытке t.remove :id, из-за внешнего ключа. Сообщение об ошибке:

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` 

Дело в том, если вся миграция побежал, то я бы поменять местами id колонку с другой, и подправить внешние ключи тоже. Итак, есть ли способ игнорировать ограничения для миграции?

+1

попытаться уронить ограничение первым затем добавить его позже http://stackoverflow.com/questions/14122031/how-to-remove-constraints-from-my-mysql-table – jvnill

+0

вы также можете просто установить uuid в качестве основного ключа и просто позволить активной записи узнать об этом. http://api.rubyonrails.org/classes/ActiveRecord/AttributeMethods/PrimaryKey/ClassMethods.html#method-i-primary_key – jvnill

ответ

0

Мой окончательный код

В if и unless заявления были там, потому что я писал и тестирование постепенно (и неудачная миграция все еще имели длительные эффекты). Главное, удаляя внешние ключи затем добавить их обратно в конце концов (удаление ключей не удаляет id полей в БД, только ограничения.

class AddUuidToProjects < ActiveRecord::Migration[5.0] 
    def up 
    # remove constraint 
    if foreign_key_exists?(:stories, :projects) 
     say("removing foreign key constraints") 

     remove_foreign_key "stories", "projects" 
     remove_foreign_key "images", "projects" 
    end 

    # create UUID id column 
    unless column_exists?(:projects, :id, :string) 
     say("adding UUID column") 

     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, uuid: SecureRandom.uuid) 
     end 

     change_table :projects do |t| 
     t.remove :id 
     t.rename :uuid, :id 
     end 
     execute "ALTER TABLE projects ADD PRIMARY KEY (id);" 
    end 

    # update foreign keys 
    if(Image.first.project_id.is_a? Integer) 
     say("updating foreign keys") 

     # change foreign key fields to STRING(36) 
     change_column :images, :project_id, :string, limit:36, null: false 
     change_column :stories, :project_id, :string, limit:36, null: false 

     Project.all.each do |p| 
     # has_one soi 
     Image.find_by(project: p.old_id).update!(project: p) 

     # has_many stories 
     Snippet.where(project_id: p.old_id).each do |s| 
      s.update!(project: p) 
     end 
     end 
    end 

    # add constraints back 
    unless foreign_key_exists?(:stories, :projects) 
     say("adding foreign key constraints back") 

     add_foreign_key "stories", "projects" 
     add_foreign_key "images", "projects" 
    end 
    end 
Смежные вопросы