Rails新增枚举列如何仅给新记录设默认值且保留旧记录为空
实现方案
你可以通过两种常见方案实现需求,都可以保证旧记录该字段保留null、仅新插入记录使用默认值:
方案1:数据库层面设置(更稳定,不依赖应用层逻辑)
先新增列不设置默认值,再单独修改列的默认值,数据库的该操作不会回溯修改旧数据,仅对后续新写入的记录生效,迁移文件写法如下:
class AddStatusToRecords < ActiveRecord::Migration[6.1] def change # 新增字段,不设置默认,旧记录自动为null add_column :records, :status, :integer # 单独设置字段默认值,仅作用于后续新插入数据 change_column_default :records, :status, 0 end end
方案2:应用层设置(适配低版本Rails场景)
如果不想在数据库层面设置默认,可通过Rails逻辑实现:
Rails 7.0及以上版本
直接使用enum原生的_default参数即可,你的语法本身是正确的,报错是因为版本不兼容:
enum status: { to_review: 0, pending: 1, processed: 2 }, _default: :to_review
Rails 6及更低版本
低版本Rails不支持enum的_default参数,可通过创建回调实现默认值赋值,仅在新记录创建时触发:
enum status: { to_review: 0, pending: 1, processed: 2 } # 仅创建新记录时,如果status为空才设置默认值 before_validation :set_default_status, on: :create private def set_default_status self.status ||= :to_review end
之前操作的问题说明
- 直接在
add_column方法中加default参数时,数据库会在新增字段的同时全表更新所有旧记录,给该字段赋值为默认值,不符合需求。 - enum设置
_default时报错,是因为你使用的Rails版本低于7.0,_default是Rails 7.0才新增的特性,低版本无法识别该参数。
内容的提问来源于stack exchange,提问作者user14777908
相关产品推荐
相关产品推荐

