You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否通过关联关系用单条简单查询获取ActiveStorage Attachment?

基于current_user作用域高效获取ActiveStorage附件的优化问题

现有模型关联关系

class User
  has_many :messages
end

class Message
  has_many_attached :files
end

需求与当前实现

我需要基于current_user的作用域,通过附件ID获取对应的ActiveStorage附件。目前的实现代码如下:

current_user.messages.joins(:files_attachments).where(active_storage_attachments: { blob_id: params[:id] }).first.files.find(params[:id])

想请教有没有更简洁且高效的实现方式?

尝试过的方案及问题

  • 尝试过以下代码,但由于record是多态关联,执行时会报错:
ActiveStorage::Attachment.includes(:record).where(messages: { user_id: current_user.id }).find_by(blob_id: params[:id])
  • 下面的方案效率太低,因为用户可能拥有大量消息,pluck(:id)会先查询所有消息ID再查附件:
ActiveStorage::Attachment.where(record_type: "Message", record_id: current_user.messages.pluck(:id)).find_by(blob_id: params[:id])

优化方案

方案1:直接构造多表JOIN查询

通过一次SQL查询关联ActiveStorage::Attachment、Message和User表,精准过滤当前用户的附件:

ActiveStorage::Attachment.joins(record: :user)
  .where(
    active_storage_attachments: { blob_id: params[:id], record_type: "Message" },
    users: { id: current_user.id }
  )
  .take

方案2:给User模型添加间接关联(最简洁)

在User模型中添加一个通过messages关联到附件的关系,后续调用会非常简洁,且Rails会自动生成高效的JOIN查询:

class User
  has_many :messages
  has_many :message_files, through: :messages, source: :files_attachments
end

# 使用时直接调用
current_user.message_files.find_by(blob_id: params[:id])

这两种方案都只执行一次SQL查询,避免了冗余操作,同时严格限定了current_user的作用域,确保数据安全。

内容的提问来源于stack exchange,提问作者lafeber

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 03:27:11