Rails如何将序列化treatments字段迁移为array: true的字符串数组?
将序列化的
treatments字段迁移为PostgreSQL原生数组字段 嘿,我来帮你搞定这个迁移的事儿!原来的treatments是用Rails的serialize存在数据库里的YAML字符串,现在要转成PostgreSQL的原生数组类型,还要保证数据不丢、属性符合要求,下面是完整的操作步骤:
第一步:生成迁移文件
先在终端跑这个命令生成迁移模板:
rails generate migration ConvertTreatmentsToArray
第二步:编写迁移代码
打开生成的迁移文件(在db/migrate/目录下),把默认内容替换成下面的代码:
class ConvertTreatmentsToArray < ActiveRecord::Migration[6.1] # 这里的版本号改成你项目用的Rails版本 def up # 先加个临时字段存转换后的数据,避免直接改原字段出问题 add_column :reviews, :treatments_temp, :string, array: true, default: [], null: false # 批量转换数据:把原来序列化的YAML转成原生数组 Review.find_each do |review| # 处理原字段可能为nil的情况,默认转成空数组 original_data = review.treatments || [] review.update_column(:treatments_temp, original_data) end # 删掉原字段,把临时字段重命名成treatments remove_column :reviews, :treatments rename_column :reviews, :treatments_temp, :treatments end def down # 回滚逻辑:把数组转回到序列化的YAML字符串 add_column :reviews, :treatments_temp, :text Review.find_each do |review| original_data = review.treatments || [] review.update_column(:treatments_temp, original_data.to_yaml) end remove_column :reviews, :treatments rename_column :reviews, :treatments_temp, :treatments end end
第三步:更新模型
一定要记得把Review模型里的serialize :treatments这一行删掉!现在PostgreSQL的原生数组会被Rails自动映射成Ruby数组,不需要手动序列化了。
一些小提醒
- 如果你用的是MySQL而不是PostgreSQL,那MySQL没有原生数组类型,得用
json类型代替,迁移里的字段要改成:json, default: [], null: false - 如果你的
reviews表数据量很大,find_each会自动分批处理,比直接用all.each更省内存 - 迁移前最好先在测试环境跑一遍,或者备份一下生产数据库,确保数据转换没问题
内容的提问来源于stack exchange,提问作者davideghz
相关产品推荐
相关产品推荐

