如何在活动存储中查找用户附件的总大小

How to find total size of user attachments in active storage

我正在使用 Rails 6。 如何获取活动存储中用户附件的总大小?

======

更新:

如果我有用户A和用户B

如何获取用户A附件的总大小?

如果你想获得 所有附件的大小 与某些记录相关联(例如 user = User.first)你可以使用这个:

ActiveStorage::Attachment.where(record: user).map(&:byte_size).sum

或使用此类查询更高效

ActiveStorage::Attachment.joins(:blob).where(record: user).sum(:byte_size)

或者像这样

ActiveStorage::Blob.
  joins(:attachments).
  where(active_storage_attachments: { record_id: user.id, record_type: user.class.name }).
  sum(:byte_size)

例如这个用户has_many_attached :images

在这种情况下,您只能获取此用户的 所有图像 的大小:

user.images.map(&:byte_size).sum

或使用此类查询更高效

user.images.joins(:blob).sum(:byte_size)

或者像这样

user.images_blobs.sum(:byte_size)

使用 include ActionView::Helpers::NumberHelper 您可以将字节大小(整数)转换为人类格式:

number_to_human_size(size_of_all_attachments)

根据@Yshmarov 和@mechnicov 的回答,我是这样做的

模型中

after_create_commit :add_user

private
def add_user
files.attachments.update(user_id: self.user.id)
end

在控制器中

    @checksize = ActiveStorage::Blob.where(id: current_user.id).map(&:byte_size).sum

可见

  <%= number_to_human_size(@checksize) %>

这不是问题的解决方案;但这帮助我解决了自己的案子。所以我发布它可能会帮助其他人,因为我认为我的情况很常见。

如果你有这个嵌套结构:

class Album < ApplicationRecord
  has_many :album_items, dependent: :destroy
end

class AlbumItem < ApplicationRecord
  belongs_to :album, counter_cache: :album_items_count
  before_destroy :purge_attachment

  has_one_attached :photo # automatically adds a `with_attached_photo` scope to prevent n+1 queries

  private
    def purge_attachment
      photo.purge_later
    end
end

计算相册总大小:

Album.first.album_items.with_attached_photo.map { |album_item| album_item.photo.byte_size }.sum

注意添加的 with_attached_photo 范围,以防止 n+1 查询。

你可以直接在数据库上做,这比这里发布的其他答案要高效得多。

假设你的 User has_many_attached :images.

查找一个用户图像的大小

您可以通过以下方式找到一个用户图片的总大小:

size_of_all_attachments = user.images_blobs.sum("active_storage_blobs.byte_size")

然后,正如 mechnicov 指出的那样,您可以包含 ActionView::Helpers::NumberHelper 以将字节大小(整数)转换为人类格式:

number_to_human_size(size_of_all_attachments)

查找所有用户图像的大小

也很轻松:

User.joins(:images_blobs).sum("active_storage_blobs.byte_size")

它的工作方式与 per the documentation 一样,has_many_attached 宏实际上在您的用户模型中创建了两个关联,就像您自己声明它们一样:

has_many :images_attachments, ...
has_many :images_blobs

这些 :images_blobs 是名为 ActiveStorage::Blob 的常规 ActiveRecord 模型,其中 table 名称为 active_storage_blob 并且它们包含一个名为 byte_size 的列,其中类型 :bigint,包含字节大小。

此处的其他答案建议使用 ActiveStorage::Attachment.where(record: User.first).map(&:byte_size).sum。但是,由于以下两个原因,这效率不高:

  1. 它将首先return所有ActiveStorage::Attachment模型;这些是 Rails 用来将您的 User 模型连接到 ActiveStorage::Blob 模型的连接模型,后者实际上包含我们之后的 byte_size 列。调用 ActiveStorage::Attachement#byte_size 会起作用,但由于 ActiveStorage::Attachment 上的 delegate_missing_to :blob 声明,所以它会使用 method_missing,这要慢得多。

  2. 由于 #1,由于 ActiveStorage::Attachment 没有 byte_size 列,它正在调用 .map,创建一个不必要的数组并加载和实例化所有这些模型是不必要的。

所以,这个答案直接进入数据库并询问已经在那里等你的总和。