Allow destroying active storage variant

Background:

When creating active storage variants, `ActiveStorage::VariantRecord` is
inserted, then a file is uploaded. Because upload can be failed, the
file can be missing even though `ActiveStorage::VariantRecord` exists.

When a file is missing, we need to delete the corresponding
`ActiveStorage::VariantRecord` but there's no API to delete just one
variant e.g., `blob.variant(resize_to_limit: [100, 100]).destroy`.

Co-authored-by: Yuichiro NAKAGAWA <ii.hsif.drows@gmail.com>
Co-authored-by: Ryohei UEDA <ueda@anipos.co.jp>
This commit is contained in:
Shouichi Kamiya 2023-01-26 10:35:39 +09:00
parent c31684294f
commit 98abeea7b6
5 changed files with 42 additions and 0 deletions

@ -1,3 +1,11 @@
* Allow destroying active storage variants
```ruby
User.first.avatar.variant(resize_to_limit: [100, 100]).destroy
```
*Shouichi Kamiya*, *Yuichiro NAKAGAWA*, *Ryohei UEDA*
* Add missing preview event to `ActiveStorage::LogSubscriber`
A `preview` event is being instrumented in `ActiveStorage::Previewer`.

@ -100,6 +100,11 @@ def image
self
end
# Deletes variant file from service.
def destroy
service.delete(key)
end
private
def processed?
service.exist?(key)

@ -27,6 +27,11 @@ def image
record&.image
end
# Destroys record and deletes file from service.
def destroy
record&.destroy
end
delegate :key, :url, :download, to: :image, allow_nil: true
private

@ -275,6 +275,15 @@ class ActiveStorage::VariantTest < ActiveSupport::TestCase
end
end
test "destroy deletes file from service" do
blob = create_file_blob(filename: "racecar.jpg")
variant = blob.variant(resize_to_limit: [100, 100]).processed
assert_changes -> { blob.service.exist?(variant.key) }, from: true, to: false do
variant.destroy
end
end
private
def process_variants_with(processor)
previous_processor, ActiveStorage.variant_processor = ActiveStorage.variant_processor, processor

@ -4,6 +4,8 @@
require "database/setup"
class ActiveStorage::VariantWithRecordTest < ActiveSupport::TestCase
include ActiveJob::TestHelper
setup do
@was_tracking, ActiveStorage.track_variants = ActiveStorage.track_variants, true
end
@ -204,4 +206,17 @@ class ActiveStorage::VariantWithRecordTest < ActiveSupport::TestCase
end
end
end
test "destroy deletes file from service" do
blob = create_file_blob(filename: "racecar.jpg")
variant = blob.variant(resize_to_limit: [100, 100]).processed
assert_equal 1, ActiveStorage::VariantRecord.count
assert blob.service.exist?(variant.key)
variant.destroy
assert_equal 0, ActiveStorage::VariantRecord.count
assert_enqueued_with(job: ActiveStorage::PurgeJob, args: [variant.image.blob])
end
end