diff --git a/lib/active_storage_validations/shared/asv_attachable.rb b/lib/active_storage_validations/shared/asv_attachable.rb index bfa2bce..af2967c 100644 --- a/lib/active_storage_validations/shared/asv_attachable.rb +++ b/lib/active_storage_validations/shared/asv_attachable.rb @@ -24,13 +24,20 @@ def validate_changed_files_from_metadata(record, attribute, metadata_keys) # Retrieve an array-like of attachables and blobs. Unlike its name suggests, # getting attachables from attachment_changes is not getting the changed - # attachables but all attachables from the has_many_attached relation. + # attachables but all attachables from the `has_many_attached` relation. + # For the `has_one_attached` relation, it only yields the new attachable, + # but if we are validating previously attached file, we need to use the blob # See #attach at: https://github.com/rails/rails/blob/main/activestorage/lib/active_storage/attached/many.rb # # Some file could be passed several times, we just need to perform the # analysis once on the file, therefore the use of #uniq. def attachables_and_blobs(record, attribute) - changes = record.attachment_changes[attribute.to_s] + changes = if record.public_send(attribute).is_a?(ActiveStorage::Attached::One) + record.attachment_changes[attribute.to_s].presence || record.public_send(attribute) + else + record.attachment_changes[attribute.to_s] + end + return to_enum(:attachables_and_blobs, record, attribute) if changes.blank? || !block_given? if changes.is_a?(ActiveStorage::Attached::Changes::CreateMany) @@ -38,7 +45,7 @@ def attachables_and_blobs(record, attribute) yield attachable, blob end else - yield changes.attachable, changes.blob + yield changes.is_a?(ActiveStorage::Attached::Changes::CreateOne) ? changes.attachable : changes.blob, changes.blob end end diff --git a/test/validators/shared_examples/works_fine_with_attachables.rb b/test/validators/shared_examples/works_fine_with_attachables.rb index d232e7a..87621be 100644 --- a/test/validators/shared_examples/works_fine_with_attachables.rb +++ b/test/validators/shared_examples/works_fine_with_attachables.rb @@ -284,6 +284,23 @@ def fixture_file_upload(filename, mime_type = nil, binary = false) end end + describe "when an invalid file has been attached on a `has_one_attached` relation without validation" do + before do + subject.using_attachable.attach(attachable_not_passing_validations) + subject.save(validate: false) + end + + let(:attachable_not_passing_validations) do + tar_file_with_image_content_type + end + + describe "when we try to validate the record afterwards" do + it "is invalid" do + assert_equal false, subject.valid? + end + end + end + describe "when using `file_fixture_upload` (or its alias `fixture_file_upload`)" do let(:attachable) { fixture_file_upload('image_150x150.png', 'image/png') }