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

Rails双启动升级遇数据库破坏性变更的适配方案咨询

解决Rails双启动时ActiveStorage service_name非空约束问题

可以通过条件迁移或模型层动态调整的方式处理该问题,以下是两种可行方案:

方案一:修改迁移文件添加版本条件

找到执行rails active_storage:update生成的迁移文件,加入基于Rails版本的逻辑判断:

class AddServiceNameToActiveStorageBlobs < ActiveRecord::Migration[6.0]
  def change
    if Rails::VERSION::MINOR >= 1
      add_column :active_storage_blobs, :service_name, :string

      reversible do |dir|
        dir.up do
          # Rails 6.1+ 环境设置非空约束并填充默认值
          change_column_null :active_storage_blobs, :service_name, false
          ActiveStorage::Blob.unscoped.update_all(service_name: ActiveStorage::Blob.service.name)
        end
      end
    else
      # Rails 6.0 环境仅添加字段,不设置非空约束
      add_column :active_storage_blobs, :service_name, :string
    end
  end
end

执行迁移后,6.0环境下字段无约束,6.1+环境下保留约束并完成默认值填充。

方案二:模型层动态移除约束验证

在初始化文件中添加条件逻辑,针对6.0版本移除service_name的非空验证:

# config/initializers/active_storage.rb
Rails.application.config.after_initialize do
  if Rails::VERSION::MINOR == 0
    ActiveStorage::Blob.class_eval do
      # 清除字段对应的非空验证规则
      _validators.delete(:service_name)
      _validate_callbacks.each do |callback|
        callback.raw_filter.try(:attributes)&.delete(:service_name)
      end
    end
  end
end

如果之前已经在6.0环境下执行过带约束的迁移,需要额外创建条件迁移来移除数据库层面的非空约束:

class RemoveServiceNameNotNullConstraintForRails60 < ActiveRecord::Migration[6.0]
  def up
    change_column_null :active_storage_blobs, :service_name, true if Rails::VERSION::MINOR == 0
  end

  def down
    if Rails::VERSION::MINOR >= 1
      change_column_null :active_storage_blobs, :service_name, false
      ActiveStorage::Blob.unscoped.update_all(service_name: ActiveStorage::Blob.service.name)
    end
  end
end

注意事项

  • 双启动环境下需分别执行db:migrate和next db:migrate,确保两个版本对应的数据库结构正确
  • 测试前要确认数据库结构与当前运行的Rails版本匹配,避免跨版本结构冲突

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 15:48:22