如何查询具有 ActiveStorage 附件的记录?

Posted

技术标签:

【中文标题】如何查询具有 ActiveStorage 附件的记录?【英文标题】:How to query records that have an ActiveStorage attachment? 【发布时间】:2019-02-24 08:26:29 【问题描述】:

给定一个带有 ActiveStorage 的模型

class User 
  has_one_attached :avatar
end

我可以检查单个用户是否有头像

@user.avatar.attached? 

但是如何返回包含(或不包含)附件的所有用户的集合?

我尝试使用 joins 返回所有带有附件的用户,但这似乎不适用于 blob 或附件表,或者我的语法可能不正确。

我确定我忽略了一些明显的东西。是否可以按照以下方式做一些事情:

User.where(attached_avatar: nil)

如果是这样,记录在哪里?

【问题讨论】:

【参考方案1】:

附件关联名称约定

附件关联使用以下约定命名:

<NAME OF ATTACHMENT>_attachment

例如,如果您有has_one_attached :avatar,则关联名称将为avatar_attachment

查询活动存储附件

现在您知道附件关联是如何命名的,您可以像使用任何其他 Active Record 关联一样使用 joins 查询它们。

例如,给定下面的User

class User
   has_one_attached :avatar
end

您可以查询所有具有该附件的User记录,如下所示

User.joins(:avatar_attachment)

这会执行INNER JOIN,它只会返回带有附件的记录。

您可以像这样查询所有没有该附件的User记录

User.
  left_joins(:avatar_attachment).
  group(:id).
  having("COUNT(active_storage_attachments) = 0")

【讨论】:

最后一个查询的 having 子句对我不起作用。相反,我使用了User.left_joins(:avatar_attachment).where('active_storage_attachments.id is NULL') ... 使用来自我之前的评论者的解决方案的纯 ActiveRecord DSL:User.left_joins(:avatar_attachment).where(active_storage_attachments: id: nil ) 多张图片是.left_joins(:avatars_attachments)(头像上是复数,附件上是【参考方案2】:

有点相关,这里是如何对附加记录执行搜索查询:

def self.search_name(search)
  with_attached_attachment.
    references(:attachment_attachment).
    where(ActiveStorage::Blob.arel_table[:filename].matches("%#search%"))
end

您只需更新with_attached_attachment:attachment_attachment 以反映您附加的模型。就我而言,我有has_one_attached :attachment

对于那些想知道的人,Arel #matches 似乎不易受到 SQL 注入攻击。

【讨论】:

【参考方案3】:

我想知道一条记录是否有任何附件(我有多个附件,比如护照和 User 的其他文档),以便我可以在 UI 中显示/隐藏一个部分。

基于答案here 我已经能够将以下方法添加到ApplicationRecord

def any_attached?
  ActiveStorage::Attachment.where(record_type: model_name.to_s, record_id: id).any?
end

然后你可以像这样使用它:

User.last.any_attached?
#=> true

【讨论】:

以上是关于如何查询具有 ActiveStorage 附件的记录?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Amazon S3 中自定义 Rails 5.2 ActiveStorage 附件的路径?

ActiveStorage 文件附件验证

Rails 5.2 的 ActiveStorage 图像上传错误:signed_id 委托给附件,但附件为零

上传前的 Rails 5.2 ActiveStorage 裁剪附件

在 factorybot 中附加 ActiveStorage 文件

从 ActiveStorage 迁移到 Shrine 的 Rake 任务