Просто сделайте это через базу данных:
Допустим, у вас есть такие устаревшие таблицы
class CreateLegacy < ActiveRecord::Migration
def change
enable_extension 'uuid-ossp'
create_table :legacies, id: :uuid do |t|
t.timestamps
end
create_table :another_legacies, id: false do |t|
t.uuid :uuid, default: 'uuid_generate_v4()', primary_key: true
t.timestamps
end
end
end
class Legacy < ActiveRecord::Base
end
class AnotherLegacy < ActiveRecord::Base
self.primary_key = 'uuid'
end
С приведенным выше кодом у вас есть:
Legacy.create.id # => "fb360410-0403-4388-9eac-c35f676f8368"
AnotherLegacy.create.id # => "dd45b2db-13c2-4ff1-bcad-3718cd119440"
Теперь добавить новый столбец идентификатора
class AddIds < ActiveRecord::Migration
def up
add_column :legacies, :new_id, :bigint
add_index :legacies, :new_id, unique: true
add_column :another_legacies, :id, :bigint
add_index :another_legacies, :id, unique: true
execute <<-SQL
CREATE SEQUENCE legacies_new_id_seq;
ALTER SEQUENCE legacies_new_id_seq OWNED BY legacies.new_id;
ALTER TABLE legacies ALTER new_id SET DEFAULT nextval('legacies_new_id_seq');
CREATE SEQUENCE another_legacies_id_seq;
ALTER SEQUENCE another_legacies_id_seq OWNED BY another_legacies.id;
ALTER TABLE another_legacies ALTER id SET DEFAULT nextval('another_legacies_id_seq');
SQL
end
def down
remove_column :legacies, :new_id
remove_column :another_legacies, :id
end
end
Значение по умолчанию добавляется после создания нового столбца, поскольку это не позволяет БД попытаться обновить все записи. => по умолчанию будет по умолчанию только для новых записей.
Старый, который вы можете засыпать, когда будете sh.
Например, один за другим
Legacy.where(new_id: nil).find_each { |l| l.update_column(:new_id, ActiveRecord::Base.connection.execute("SELECT nextval('legacies_new_id_seq')")[0]['nextval'].to_i) }
AnotherLegacy.where(id: nil).find_each { |l| l.update_column(:id, ActiveRecord::Base.connection.execute("SELECT nextval('another_legacies_id_seq')")[0]['nextval'].to_i) }
Если вы хотите, вы можете сначала выполнить обратную засыпку, а затем добавить значения по умолчанию, а затем снова выполнить обратную засыпку.
Если вы довольны значениями, просто измените первичный ключ:
class Legacy < ActiveRecord::Base
self.primary_key = 'new_id'
def uuid
attributes['id']
end
end
class AnotherLegacy < ActiveRecord::Base
self.primary_key = 'id' # needed as we have not switched the PK in the db
end
Legacy.first.id # => 1
Legacy.first.uuid # => "fb360410-0403-4388-9eac-c35f676f8368"
AnotherLegacy.first.id # => 1
AnotherLegacy.first.uuid # => "dd45b2db-13c2-4ff1-bcad-3718cd119440"
Наконец вы нужна еще одна миграция, чтобы заменить первичный ключ на новый идентификатор.
Самое главное, чтобы избежать простоев:
- создать столбец
- обеспечить заполнение новых записей по умолчанию каким-то образом (по умолчанию или триггером)
- засыпать старую запись
- добавить ограничения
- переключиться на новый столбец
- , тогда вы можете удалить старый (если вы уверены, что он не используется)
пс. Не уверен, почему вы хотите полностью переключиться с uuids, они лучше, если вы хотите ссылаться на записи из внешних приложений
ps.2.0. если вам нужно уметь Legacy.find("fb360410-0403-4388-9eac-c35f676f8368")
и Legacy.find(123)
, возможно, попробуйте https://github.com/norman/friendly_id
friendly_id :uuid, use: [:slugged, :finders]