【问题标题】:How to clean up ActiveStorage record and storage folder of development environment?如何清理开发环境的ActiveStorage记录和存储文件夹?
【发布时间】:2020-10-08 14:18:05
【问题描述】:

根据 Rails (edge6.0) 指南,我们可以分别调用以下语句对System Test 和Integration Test 中使用的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


【解决方案1】:

我认为问题本身中@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)
    

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

    【讨论】:

    • 我不知道purge 是否可用,因为v5.2.3。
    • 虽然我不确定是否有机会获得孤立文件(问题中的第 2 位),但这些语句只会解决问题中的第 1 位。
    • 是的,如果你有没有 blob 的文件,我会说你不走运,你必须使用 ruby​​ 遍历每个文件夹,并在删除之前检查数据库中是否存在密钥,文件名是与blob.key 匹配的哈希。但是,如果您已经存储了大量文件,这在磁盘上将是一项昂贵的任务。
    • edge guide 建议ActiveStorage::Blob.unattached.find_each(&amp;:purge_later)。 unattached 范围自 v5.2.3 起可用
    • unattached 只是一个与上面相同的作用域,但是是的,对于 left_joins github.com/rails/rails/blob/main/activestorage/app/models/…,这是更好的语法。 purge_later 也可能是提高性能的正确方法,除非您已经在工作或后台任务中,尽管即使这样将其卸载到单独的工作可能会释放一些内存。
    【解决方案3】:
    ActiveStorage::Blob.unattached.each(&:purge_later)
    

    如果您不希望它在后台发生,或者只是 purge。

    【讨论】:

      猜你喜欢
      • 2011-05-31
      • 2021-09-27
      • 1970-01-01
      • 2014-05-30
      • 2022-08-03
      • 2021-11-07
      • 2021-01-27
      • 2011-04-01
      • 1970-01-01
      相关资源
      最近更新 更多