Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Validations not locating file uploaded using fixture_file_upload using vips #323

Closed
douglasmorgen opened this issue Dec 12, 2024 · 9 comments · Fixed by #325
Closed

Validations not locating file uploaded using fixture_file_upload using vips #323

douglasmorgen opened this issue Dec 12, 2024 · 9 comments · Fixed by #325
Assignees
Labels
bug Something isn't working

Comments

@douglasmorgen
Copy link

douglasmorgen commented Dec 12, 2024

validations not locating file fixtures when using vips

Issue Summary:
Updating from 1.3.4 to 1.3.5 causes test failures when running validations using vips

Steps to Reproduce:

  1. Update active_storage_validations from 1.3.4 to 1.3.5.
  2. Upload a file in rspec through fixture_file_upload...file doesn't get found during validations

Observed Behavior:

Once you upgrade to 1.3.5:

post = build(:post)
file = fixture_file_upload('spec/fixtures/files/arrafund_logo.png', 'image/png')
post.media_files.attach(file)
[1] pry(#<RSpec::ExampleGroups::Post::Validations>)> post.valid?
ActiveStorage::FileNotFoundError: ActiveStorage::FileNotFoundError
from ~/.asdf/installs/ruby/3.3.6/lib/ruby/gems/3.3.0/gems/activestorage-7.2.2.1/lib/active_storage/service/disk_service.rb:49:in `rescue in block in download_chunk'
Caused by Errno::ENOENT: No such file or directory @ rb_sysopen - <root>/tmp/storage/zy/fe/zyferqrrstzqlmzk8mapyxpzic17
from /Users/dmorgen/.asdf/installs/ruby/3.3.6/lib/ruby/gems/3.3.0/gems/activestorage-7.2.2.1/lib/active_storage/service/disk_service.rb:44:in `initialize'

Expected Behavior:

[2] pry(#<RSpec::ExampleGroups::Post::Validations>)> post.valid?

=> true

Environment:

  • Rails version: 7.2.2.1
  • Ruby version: 3.3.6
    -pry(#RSpec::ExampleGroups::Post::Validations)> ActiveStorage.analyzers
    => [ActiveStorage::Analyzer::ImageAnalyzer::Vips, ActiveStorage::Analyzer::ImageAnalyzer::ImageMagick, ActiveStorage::Analyzer::VideoAnalyzer, ActiveStorage::Analyzer::AudioAnalyzer]

Please let me know if additional information is needed. Thank you for your work on this gem!

@Mth0158 Mth0158 self-assigned this Dec 12, 2024
@Mth0158 Mth0158 added the bug Something isn't working label Dec 12, 2024
@Mth0158
Copy link
Collaborator

Mth0158 commented Dec 12, 2024

Hi @douglasmorgen,
Thanks for reporting the issue. From 1.3.4 to 1.3.5 we changed things a bit, we have refactored the part of the app using Vips/MiniMagick and the method that uses download_chunk, therefore your issue...
Let me check this up, I think it will be easy to fix (hopefully).

Could you provide your model validations to help this out?

@Mth0158
Copy link
Collaborator

Mth0158 commented Dec 12, 2024

@douglasmorgen I am not able to reproduce your issue :/ can you give me a bit more context? Like model validations? And maybe the complete caller trace?
I made a PR (#325) and have no issue with file_fixture_upload on my side

@douglasmorgen
Copy link
Author

douglasmorgen commented Dec 12, 2024

Stack trace is attached I think the relevant part is
# /Users/dmorgen/.asdf/installs/ruby/3.3.6/lib/ruby/gems/3.3.0/gems/activestorage-7.2.2.1/app/models/active_storage/blob.rb:289:in download_chunk' # /Users/dmorgen/.asdf/installs/ruby/3.3.6/lib/ruby/gems/3.3.0/gems/active_storage_validations-1.3.5/lib/active_storage_validations/shared/asv_attachable.rb:87:in attachable_io'
# /Users/dmorgen/.asdf/installs/ruby/3.3.6/lib/ruby/gems/3.3.0/gems/active_storage_validations-1.3.5/lib/active_storage_validations/shared/asv_attachable.rb:70:in attachable_content_type_rails_like' # /Users/dmorgen/.asdf/installs/ruby/3.3.6/lib/ruby/gems/3.3.0/gems/active_storage_validations-1.3.5/lib/active_storage_validations/content_type_validator.rb:57:in set_attachable_cached_values'

Validation is
has_many_attached :media_files

 validates :media_files, attached: true, limit: { min: 1, max: 10 },
                      size: { less_than: 100.megabytes },
                      content_type: %i[png jpg jpeg mp4 mpg mpeg pdf]

Stack trace.txt

@Mth0158
Copy link
Collaborator

Mth0158 commented Dec 12, 2024

Mmm this is quite weird, you are attaching a Rack::Test::UploadedFile instance (that is what file_fixture_upload generates) to your post.media_files attribute.
But when validating the record, somehow the ASV attachable_io method is finding your attachable as an ActiveStorage::Blob 🤔, therefore the issue down the road.

A few questions:

  • Do you have something in your code that could overrides fixture_file_uploadmethod?
  • Do you have some callback that would run before the validate and raising this issue?
  • Can you provide the relevant part of your post factory? There might be something to investigate there also?

@evaniainbrooks
Copy link

We encountered this as well.

I noticed that eventually, attachable_content_type_rails_like(attachable) gets called with an ActiveStorage::Blob that is not persisted, and this is when it raises.

Changing the test subject from build(:factory_record) call to create(:factory_record) resolved the issue for us.

@Mth0158
Copy link
Collaborator

Mth0158 commented Dec 16, 2024

Hi @evaniainbrooks,
Thanks for reporting the issue, it narrows the culprit scope, I'll investigate it this week but it will take some days as I am a bit busy, I'll let you know when it's released :)

@Mth0158
Copy link
Collaborator

Mth0158 commented Dec 20, 2024

I guess it can be related to #328

@Mth0158 Mth0158 reopened this Dec 21, 2024
@Mth0158
Copy link
Collaborator

Mth0158 commented Dec 30, 2024

Hi @douglasmorgen,
I tried reproducing your issue but was not successful :/

For example, I set up the following model:

class Camp::Lecture < ApplicationRecord
  has_one_attached :video
  validates :video,
            size: { less_than: 20.megabytes },
            content_type: { with:/\Avideo\/.*\z/, spoofing_protection: true }
end

With the related build code using factory_bot:

lecture = build(:lecture)
vid = Rack::Test::UploadedFile.new(File.join("spec/fixtures/files/example.mp4"), 'video/mp4')
lecture.video.attach(vid)
lecture.valid?

And I have no issue whatsoever. The fixture_file_upload method does exactly vid = Rack::Test::UploadedFile.new(File.join("spec/fixtures/files/example.mp4"), 'video/mp4') and therefore do not try to download from a blob but rather from a Rack::Test::UploadedFile.

The issue you had will not reproduce in 1.4.0 if you do not have spoofing_protection: true activated since we changed things a bit to enhance perf.

My only ideas for your issue are:

  1. Your file_fixture_upload does not return a Rack::Test::UploadedFile, but a blob without a backing file, like the below factory example:
  factory :active_storage_blob, class: 'ActiveStorage::Blob' do
    key { Faker::Alphanumeric.alphanumeric(number: 24) }
    filename { Faker::Alphanumeric.alpha(number: 15) }
    metadata { { "identified" => true } }
    byte_size { Faker::Number.number(digits: 5) }
    checksum { Faker::Crypto.md5 }

    trait :image do
      content_type { "image/jpeg" }

      transient do
        image_width { 0 }
        image_height { 0 }
      end

      after(:build) do |blob, evaluator|
        blob.metadata.merge!(
          width: evaluator.image_width,
          height: evaluator.image_height
        )
      end
    end
  end

This would indeed cause issue because the active_storage_blob instance has no file related, therefore trying to download the blob io will cause an ActiveStorage::FileNotFoundError

  1. fixture_file_upload('spec/fixtures/files/arrafund_logo.png', 'image/png') points to a file that does not exist, therefore the issue?

I am a bit short of ideas, if you have any let me know and I'll do the best to help you

@douglasmorgen
Copy link
Author

It is fixed as of 1.4.0 thanks so much for your help.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
3 participants