You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Rails迁移为Active Record模型的JSON字段新增键且不覆盖现有数据

实现Rails JSON字段新增键且不覆盖原有数据的方案

你不需要提前备份数据再逐行写回,借助数据库原生的JSON合并能力即可安全完成需求,完整操作步骤如下:

1. 生成迁移文件

执行命令创建迁移,注意把示例中的Users替换为你自己的模型名:
rails g migration add_address_key_to_users_data

2. 编写迁移逻辑

根据你使用的数据库类型选择对应代码,以下逻辑同时满足两个需求:

  • 新创建的记录默认在data字段中携带空值address键
  • 现有记录仅新增address键,不修改原有name、number的值

PostgreSQL(推荐使用jsonb类型字段)

class AddAddressKeyToUsersData < ActiveRecord::Migration[7.0] # 替换为你对应的Rails版本
  def change
    # 给新记录设置默认值,不会影响现有记录
    change_column_default :users, :data, from: {"name": "", "number": ""}, to: {"name": "", "number": "", "address": ""}
    
    # 给现有记录补address字段,使用PG的jsonb合并操作符||,仅新增不存在的键
    reversible do |dir|
      dir.up do
        execute <<~SQL
          UPDATE users
          SET data = data || '{"address": ""}'::jsonb
          WHERE data ? 'address' = false; -- 仅更新还没有address键的记录,保障幂等性
        SQL
      end
    end
  end
end

MySQL

class AddAddressKeyToUsersData < ActiveRecord::Migration[7.0]
  def change
    change_column_default :users, :data, from: {"name": "", "number": ""}, to: {"name": "", "number": "", "address": ""}
    
    reversible do |dir|
      dir.up do
        execute <<~SQL
          UPDATE users
          SET data = JSON_MERGE_PATCH(data, '{"address": ""}')
          WHERE JSON_CONTAINS_PATH(data, 'one', '$.address') = 0;
        SQL
      end
    end
  end
end

3. 模型层可选配置

如果你不想在数据库层面设置默认,也可以在模型中通过store_accessor配置默认值,代码更灵活:

class User < ApplicationRecord
  # Rails 7+ 支持直接给store_accessor加default参数
  store_accessor :data, :name, :number, :address, default: ""
  
  # 低于Rails 7版本用after_initialize回调实现
  # after_initialize do
  #   return unless has_attribute?(:data)
  #   self.address ||= ""
  # end
end

注意事项

  • 所有操作默认不会修改现有记录的name、number值,仅新增不存在的address键
  • 迁移中加了WHERE条件过滤已经存在address键的记录,哪怕重复执行迁移也不会覆盖已有的address值
  • 大数据量场景下直接执行SQL更新比遍历每条ActiveRecord对象效率高几个数量级

内容的提问来源于stack exchange,提问作者Petesta

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 16:06:06