Reputation: 123
I'm getting an error testing the ActiveStorage attachment. The code is something like this:
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
I'm getting the following error
Minitest::UnexpectedError: ActiveStorage::FileNotFoundError: ActiveStorage::FileNotFoundError
when @assembly.image.download is called. The attached?
assertion is passing, but I can't figure out why the download of the file is failing. Also, nothing shows up in the tmp/storage
directory, where the ActiveStorage is configured to store files.
Upvotes: 8
Views: 3723
Reputation: 671
I had a same on production and in my case it happened because user uploaded broken png file
so I added validation to prevent corrupted files from being uploaded using the demension option, because broken images will never have a dimension value.
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
also I used these 3 gems to make everything work properly
#Gemfile
gem "active_storage_validations"
gem "ruby-vips"
gem "image_processing"
Upvotes: 0
Reputation: 401
You can create the blob directly (which is how the direct upload process works) and then attach it so the blob is guaranteed to already be uploaded.
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)
Upvotes: 1
Reputation: 1550
While digging in the ActiveStorage code I found this snipped which relies on actual database commits to execute the document upload (or save to disc):
after_commit(on: %i[ create update ]) { attachment_changes.delete(name.to_s).try(:upload) }
In case you use database transactions in the test environment this will then not store the document.
To solve this you can trigger the commit callback manually:
run_callbacks(:commit)
So in your case this might work:
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
Upvotes: 7
Reputation: 15248
Try this
@assembly = Assembly.create(name: assemblies(:head_gasket).name)
@assembly.image.attach(io: File.open('/path/to/file'), filename: 'file.name', content_type: 'mime/type')
Upvotes: 0