如何清理开发环境的ActiveStorage记录和存储文件夹?

问题描述 投票:0回答:4

根据Rails (edge

6.0
)指南,我们可以通过分别调用以下语句来对系统测试集成测试中使用的ActiveStorage进行维护工作

  # System Test
  FileUtils.rm_rf("#{Rails.root}/storage_test")

  # Integration Test
  FileUtils.rm_rf(Rails.root.join('tmp', 'storage'))

我想知道-

Rails 是否有任何内置函数或 rake 命令或 gem 可以执行以下操作?

  1. 删除孤立 blob(
    ActiveStorage::Blob
    记录不再与任何
    ActiveStorage::Attachment
    记录关联)
  2. 删除孤立文件(不再与任何
    ActiveStorage::Blob
    记录关联的文件)

我没有看到任何与

rails --tasks
相关的 rake 任务。

目前我正在使用

# remove blob not associated with any attachment
ActiveStorage::Blob.where.not(id: ActiveStorage::Attachment.select(:blob_id)).find_each do |blob|
  blob.purge # or purge_later
end

这个脚本用于清理孤立文件(通过

rails console

# run these ruby statement in project rails console
# to remove the orphan file
include ActionView::Helpers::NumberHelper

dry_run = true
files = Dir['storage/??/??/*']

orphan = files.select do |f|
  !ActiveStorage::Blob.exists?(key: File.basename(f))
end

sum = 0
orphan.each do |f|
  sum += File.size(f)
  FileUtils.remove(f) unless dry_run
end

puts "Size: #{number_to_human_size(sum)}"
ruby-on-rails rails-activestorage
4个回答
10
投票
ActiveStorage::Blob.unattached.each(&:purge_later)

或者只是

purge
(如果您不希望它在后台发生)。


3
投票

我认为问题本身中@Tun 建议的解决方案工作正常。我将其写在 Rake Tasks 版本中,以防为下一个人节省一些时间:

# Usage:
#   - rake "remove_orphan_blobs"
#   - rake "remove_orphan_blobs[false]"
desc "Remove blobs not associated with any attachment"
task :remove_orphan_blobs, [:dry_run] => :environment do |_t, args|
  dry_run = true unless args.dry_run == "false"

  puts("[#{Time.now}] Running remove_orphan_blobs :: INI#{" (dry_run activated)" if dry_run}")

  ActiveStorage::Blob.where.not(id: ActiveStorage::Attachment.select(:blob_id)).find_each do |blob|
    puts("Deleting Blob: #{ActiveStorage::Blob.service.path_for(blob.key)}#{" (dry_run activated)" if dry_run}")
    blob.purge unless dry_run
  end

  puts("[#{Time.now}] Running remove_orphan_blobs :: END#{" (dry_run activated)" if dry_run}")
end

# Usage:
#   - rake "remove_orphan_files"
#   - rake "remove_orphan_files[false]"
desc "Remove files not associated with any blob"
task :remove_orphan_files, [:dry_run] => :environment do |_t, args|
  include ActionView::Helpers::NumberHelper
  dry_run = true unless args.dry_run == "false"

  puts("[#{Time.now}] Running remove_orphan_files :: INI#{" (dry_run activated)" if dry_run}")

  files = Dir["storage/??/??/*"]
  orphan_files = files.select do |file|
    !ActiveStorage::Blob.exists?(key: File.basename(file))
  end

  sum = 0
  orphan_files.each do |file|
    puts("Deleting File: #{file}#{" (dry_run activated)" if dry_run}")
    sum += File.size(file)
    FileUtils.remove(file) unless dry_run
  end

  puts "Size Liberated: #{number_to_human_size(sum)}#{" (dry_run activated)" if dry_run}"

  puts("[#{Time.now}] Running remove_orphan_files :: END#{" (dry_run activated)" if dry_run}")
end

2
投票

现在有一种更简单的方法,不确定它何时改变,但有一个警告(它会留下空文件夹):

# rails < 6.1
ActiveStorage::Blob.left_joins(:attachments).where(active_storage_attachments: { id: nil }).find_each(&:purge)

# rails >= 6.1
ActiveStorage::Blob.missing(:attachments).find_each(&:purge)

这将删除数据库中的记录并删除磁盘上的物理文件,但保留文件所在的文件夹。


0
投票

在 Rails 7.1.3 中工作:

ActiveStorage::Blob.unattached.each(&:purge)

© www.soinside.com 2019 - 2024. All rights reserved.