在销毁带有附件的记录后,我无法清除存储在 S3 存储桶中的图像。我搜索了很久,但我无法弄清楚是什么导致了这个问题。
我的 Tour 型号有两种类型的附件:
cover_image
(单个)和 images
(多个)。
创作过程进展顺利。我使用 Rails 作为 API,发送带有表单数据的 POST 请求。在我的控制器中,我附加了这样的图像:
def create_tour
if(@params[:tour_cover_image].present?)
tour_images = @params.select{ |key, _| key.to_s.start_with?('tour_image-') }
tour = Tour.new(@tour_params)
tour.save!
tour.cover_image.attach(
io: File.open(@params[:tour_cover_image].tempfile),
filename: @params[:tour_cover_image].original_filename,
content_type: @params[:tour_cover_image].content_type,
key: "public/tours/#{tour.id}/cover_image/#{SecureRandom.uuid}-#{@params[:tour_cover_image].original_filename}"
)
tour_images.each do |key, image|
tour.images.attach(
io: File.open(image.tempfile),
filename: image.original_filename,
content_type: image.content_type,
key: "public/tours/#{tour.id}/images/#{SecureRandom.uuid}-#{image.original_filename}"
)
end
else
tour = Tour.new(@tour_params.except(:images, :cover_image))
tour.save!
end
tour
end
我还创建了一个 Rake 任务,通过销毁所有记录来清理我的开发数据库:
namespace :tours do
desc "This will destroy all tours and their dependencies"
task destroy_all: :environment do
Tour.destroy_all
puts "All tours and their dependencies have been destroyed"
end
end
在我的 Tour 模型中,我添加了一个回调,以便在记录被销毁时清除 S3 中的所有图像:
class Tour < ApplicationRecord
has_many :tour_vehicles_tours, dependent: :destroy
has_many :tour_vehicles, through: :tour_vehicles_tours
has_many :schedule_stop, dependent: :destroy
belongs_to :user
has_one_attached :cover_image
has_many_attached :images
before_destroy :purge_images
def purge_images
images.purge
cover_image.purge
end
end
问题来了:
当我通过 Rake 任务运行
Tour.destroy_all
时,会触发 purge_images
回调,但只有 cover_image
会从 S3 中删除。图像不会被清除,并且 images.attached?
在回调中返回 false。
但是,当我使用
Tour.last.destroy
手动销毁记录时,回调会按预期工作,并且 cover_image 和图像都会从 S3 中清除。
什么可能导致 destroy_all 和 destroy 之间出现这种不一致?
来自文档的您好https://apidock.com/rails/ActiveRecord/Relation/destroy_all它应该按预期工作。您可以尝试添加它并查看它记录的内容吗?
def purge_images
# Add error handling and logging
begin
if cover_image.attached?
cover_image.purge
Rails.logger.info "Successfully purged cover image for Tour #{id}"
end
if images.attached?
images.purge
Rails.logger.info "Successfully purged #{images.count} images for Tour #{id}"
end
rescue StandardError => e
Rails.logger.error "Failed to purge images for Tour #{id}: #{e.message}"
# Optionally re-raise the error if you want to halt the process
# raise e
end
end
另一件事是你想要
after_destroy
回调而不是 before_destroy
after_destroy_commit :purge_images
您可以在此处找到完整的回调列表https://guides.rubyonrails.org/active_record_callbacks.html#destroy-callbacks