问题是关于rails数据库迁移。
当前数据库包含一个假设为布尔变量的两个条目,如数据库方案中所示:
create_table "table_name", force: :cascade do |t|
...
t.string "yes_boolvar"
t.string "no_boolvar"
...
end
我需要将它转换为一个单独的布尔变量,如下所示:
t.boolean "boolvar"
我考虑重命名'yes_boolvar',将其类型从字符串更改为布尔值,然后根据一些读数删除'no_boolvar'列,如下所示:
t.rename :yes_boolvar,
:boolvar
t.change :boolvar,
:boolean
t.remove :no_boolvar
但是,在复制变量值时,这只会考虑'yes_ *'而不是'no_ *'的真值。有没有办法成功迁移var,以便考虑两个变量的真值(或零值)。
这取决于您的应用程序。
如果没有人可以更新这些值(即它不是用户配置文件中的字段),那么您可以:
boolvar
的代码另一种解决方案是以3个步骤迁移数据:
no_boolvar
列我想可以将前两个动作合并为一个迁移(但我更喜欢将它们分开)。
我建议你处理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
。
这大致是我写的迁移(我没有运行代码,但它应该工作):
# 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