能否通过关联关系用单条简单查询获取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
相关产品推荐
相关产品推荐

