#ruby-on-rails #database-migration #ruby-on-rails-5.1
#ruby-on-rails #база данных-миграция #ruby-on-rails-5.1
Вопрос:
Вопрос касается миграции базы данных rails.
Текущая база данных содержит две записи для предположительно логической переменной, как в схеме базы данных следующим образом:
create_table "table_name", force: :cascade do |t|
...
t.string "yes_boolvar"
t.string "no_boolvar"
...
end
Мне нужно преобразовать ее в одну логическую переменную следующим образом:
t.boolean "boolvar"
Я подумал о переименовании ‘yes_boolvar’, изменении его типа со string на boolean, а затем удалении столбца ‘no_boolvar’ на основе некоторых показаний, например, следующего:
t.rename :yes_boolvar,
:boolvar
t.change :boolvar,
:boolean
t.remove :no_boolvar
Однако при копировании значения переменной будет учитываться только значение истинности ‘yes_ *’, а не ‘no_ *’. Есть ли способ успешно перенести var, чтобы были приняты во внимание истинностные (или нулевые) значения обоих переменных.
Ответ №1:
Это зависит от вашего приложения.
Если никто не может обновить эти значения (т. Е. Это не поле в профиле пользователя), то вы можете:
- создать дамп базы данных
- запустите миграцию
- выполните код, который заполнит
boolvar
Другим решением является перенос данных в 3 этапа:
- при первой миграции столбец переименовывается
- вторая миграция переносит данные
- третья миграция удаляет
no_boolvar
столбец
Я предполагаю, что можно объединить первые два действия в одну миграцию (но я предпочитаю, чтобы они были разделены).
Ответ №2:
Я рекомендую вам выполнить 3 миграции. Для начала создайте миграцию, добавив boolean: :boolvar
class AddBoolvarToTableName < ActiveRecord::Migration
def up
add_column :table, :boolvar, :boolean
end
def down
remove_column :table, :boolvar
end
end
После создайте новую миграцию для обработки данных:
class RepopulateBooleanValues < ActiveRecord::Migration[5.0]
def change
YourClass.all.each do |record|
# put the logic here like:
record.boolvar = record.yes_boolvar == 'true'
# or
record.boolvar = record.not_boolvar == 'false'
# I'am not sure whats the content of yes_boolvar and not_boolvar, elaborate the logic here
record.save
end
end
end
Чтобы завершить это, просто создайте новую миграцию, удалив yes_boolvar
и no_boolvar
.
Ответ №3:
Примерно такую миграцию я бы написал (я не запускал код, но она должна сработать):
# This ensures the migration to work
# regardless the customizations on your original model
class TempModel < ActiveRecord::Base
self.table_name = 'table_name'
end
class MyMigration < ActiveRecord::Migration[5.0]
def up
add_column :table_name, :boolvar, :boolean
TempModel.reset_column_information
TempModel.find_each do |record|
# Decide some logic here about how to migrate values from yes_boolvar
# and no_boolvar columns to boolvar column
boolvar_value = record.yes_boolvar || !record.no_boolvar
record.update_column :boolvar, boolvar_value
end
remove_column :table_name, :yes_boolvar
remove_column :table_name, :no_boolvar
end
def down
add_column :table_name, :yes_boolvar, :string
add_column :table_name, :no_boolvar, :string
TempModel.reset_column_information
TempModel.find_each do |record|
# Decide some logic here about how to handle yes_boolvar
# and no_boolvar values
record.update_columns yes_boolvar: record.boolvar,
no_boolvar: !record.boolvar
end
remove_column :table_name, :boolvar
end
end