升级Rails至7.0.6后PG::NotNullViolation错误求助
解决Rails 7升级后Heroku预发布环境Active Storage
service_name非空约束错误 问题根源
Rails 6.1+版本的Active Storage在active_storage_blobs表中新增了service_name字段,并设置为NOT NULL约束。本地测试正常但部署到Heroku预发布环境报错,通常是迁移未正确执行、环境配置缺失或延迟任务代码未适配新字段导致。
解决方案
1. 验证数据库迁移状态
登录Heroku预发布环境,检查添加service_name字段的迁移是否已执行:
heroku run rails db:migrate:status --app <你的预发布APP名称>
找到类似20210106183435_add_service_name_to_active_storage_blobs.rb的迁移文件,确认状态为up。如果是down,手动执行迁移:
heroku run rails db:migrate --app <你的预发布APP名称>
2. 确认Active Storage配置正确性
- 检查
config/storage.yml,确保预发布环境对应的service配置存在且名称正确:staging: service: S3 access_key_id: <%= ENV['AWS_ACCESS_KEY_ID'] %> secret_access_key: <%= ENV['AWS_SECRET_ACCESS_KEY'] %> region: <%= ENV['AWS_REGION'] %> bucket: <%= ENV['AWS_STAGING_BUCKET'] %> - 检查预发布环境配置文件(如
config/environments/staging.rb),确保指定了正确的service:config.active_storage.service = :staging - 确保延迟任务(Sidekiq/Delayed Job等)启动时加载的是预发布环境配置,避免使用默认的production配置。
3. 适配延迟任务中的Blob创建代码
如果代码中手动创建ActiveStorage::Blob,需添加service_name参数:
# Rails 5.2 旧代码 blob = ActiveStorage::Blob.create!( key: key, filename: filename, content_type: content_type, byte_size: byte_size, checksum: checksum ) # Rails 7 适配后代码 blob = ActiveStorage::Blob.create!( key: key, filename: filename, content_type: content_type, byte_size: byte_size, checksum: checksum, service_name: Rails.configuration.active_storage.service )
如果使用模型的attach方法,确保模型关联的Active Storage继承全局配置即可,无需手动传参。
4. 清理Heroku缓存并重启进程
缓存可能导致旧代码或配置未生效,执行以下命令:
# 清理临时文件缓存 heroku run rails tmp:clear --app <你的预发布APP名称> # 重启主应用进程 heroku restart --app <你的预发布APP名称> # 重启延迟任务进程(以Sidekiq为例) heroku ps:restart worker --app <你的预发布APP名称>
5. 手动修复现有Blob数据(可选)
如果迁移已执行但存在service_name为空的历史数据,可通过SQL批量更新:
# 进入Heroku数据库控制台 heroku run rails dbconsole --app <你的预发布APP名称>
执行SQL(替换为你的service名称):
UPDATE active_storage_blobs SET service_name = 'staging' WHERE service_name IS NULL;
内容的提问来源于stack exchange,提问作者Srilatha
相关产品推荐
相关产品推荐

