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
相关产品推荐
相关产品推荐

