我在测试 ActiveStorage 附件时遇到错误。代码是这样的:
class AssemblyTest < ActiveSupport::TestCase
test 'Updating svg attachment should upload the updated file' do
@assembly = Assembly.create(name: assemblies(:head_gasket).name,
image:
fixture_file_upload('files/track-bar.svg', 'image/svg+xml'))
assert @assembly.image.attached?
assert_not_empty @assembly.image.download
end
end
我收到以下错误
Minitest::UnexpectedError: ActiveStorage::FileNotFoundError: ActiveStorage::FileNotFoundError
当 @ assembly.image.download 被调用时。 attached?
断言正在通过,但我不明白为什么文件下载失败。此外,ActiveStorage 配置为存储文件的tmp/storage
目录中也没有显示任何内容。
在挖掘 ActiveStorage 代码时我发现了这个片段,它依赖于实际的数据库提交来执行文档上传(或保存到光盘):
after_commit(on: %i[ create update ]) { attachment_changes.delete(name.to_s).try(:upload) }
如果您在测试环境中使用数据库事务,则不会存储文档。
要解决这个问题,您可以手动触发提交回调:
run_callbacks(:commit)
所以在你的情况下这可能有效:
class AssemblyTest < ActiveSupport::TestCase
test 'Updating svg attachment should upload the updated file' do
@assembly = Assembly.create(name: assemblies(:head_gasket).name,
image:
fixture_file_upload('files/track-bar.svg', 'image/svg+xml'))
@assembly.run_callbacks(:commit) # Run commit callback to store on disk
assert @assembly.image.attached?
assert_not_empty @assembly.image.download
end
end
试试这个
@assembly = Assembly.create(name: assemblies(:head_gasket).name)
@assembly.image.attach(io: File.open('/path/to/file'), filename: 'file.name', content_type: 'mime/type')
您可以直接创建 Blob(这就是直接上传过程的工作原理),然后附加它,以便保证 Blob 已上传。
blob = ActiveStorage::Blob.create_and_upload!(
io: File.open(Rails.root.join("test/fixtures/files/test.csv")),
filename: "test.csv",
content_type: "text/csv",
identify: false
)
@model.file.attach(blob)
我也有同样的情况,就我而言,这是因为用户上传了损坏的 png 文件
因此我添加了验证以防止使用尺寸选项上传损坏的文件,因为损坏的图像永远不会有尺寸值。
class YourModel < ApplicationRecord
validates :image, content_type: %w[image/png image/jpg image/jpeg],
dimension: { width: { min: 50, max: 5000 },
height: { min: 50, max: 5000 }}
end
我还使用了这 3 个宝石来让一切正常工作
#Gemfile
gem "active_storage_validations"
gem "ruby-vips"
gem "image_processing"