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

如何阻止Rails 6测试删除操作删除Active Storage的fixture附件文件

解决方案

针对Rails 6 + RSpec栈下事务测试时Active Storage fixture文件被永久删除的问题,有两种可落地的解决方案,无需修改业务逻辑:

方案1:禁用测试环境下Active Storage的实际文件删除逻辑

该方案适合不需要验证文件是否被实际删除的测试场景,零侵入业务代码:
在config/initializers/active_storage.rb中添加以下代码:

if Rails.env.test?
  # 覆写磁盘存储服务的删除方法,测试环境下不实际删除本地文件
  ActiveStorage::Service::DiskService.class_eval do
    def delete(key)
    end

    def delete_prefixed(prefix)
    end
  end
end

修改后Active Storage的purge操作只会操作数据库记录,不会修改本地文件系统,事务回滚后数据库记录恢复,原文件也保留在存储目录中,不影响后续测试运行。

方案2:通过RSpec钩子每次测试前恢复fixture附件文件

该方案适合需要验证文件删除逻辑是否正常执行的测试场景:

  1. 提前将fixture关联的所有静态附件文件,按照blob key对应的目录结构,存放在spec/fixtures/files/active_storage_fixtures目录下
  2. 在spec/rails_helper.rb中添加全局钩子,每次测试前将静态文件复制到测试存储目录:
RSpec.configure do |config|
  # 单测运行前恢复所有fixture附件文件
  config.before(:each) do
    fixture_attachment_dir = Rails.root.join('spec', 'fixtures', 'files', 'active_storage_fixtures')
    test_storage_dir = Rails.root.join('tmp', 'storage') # Rails测试环境默认Active Storage存储路径
    FileUtils.rm_rf(Dir.glob("#{test_storage_dir}/*"))
    FileUtils.cp_r(Dir.glob("#{fixture_attachment_dir}/*"), test_storage_dir)
  end

  # 若使用purge_later异步删除,需开启Active Job inline执行
  config.before(:each) do
    ActiveJob::Base.queue_adapter = :inline
  end
end

注意事项

  • 若你的Active Storage测试存储路径做了自定义修改,需要对应调整上述代码中的test_storage_dir路径
  • Fixture中blob记录的key需要和静态文件的存储路径一一对应,比如key为2fxqd3nfi7sdf89jwk2sdf的文件,存放路径应为ab/cd/2fxqd3nfi7sdf89jwk2sdf,前两位字符拆分为两级子目录

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 23:15:01