如何通过原生SQL查询获取用户(Profile)的Avatar URL?
在Rails原生SQL中关联Active Storage获取头像完整URL
要在原生SQL中获取头像的完整URL,你需要关联Active Storage的两个核心表:active_storage_attachments(记录附件与模型的关联关系)和active_storage_blobs(存储附件元数据,包括文件唯一标识key)。
修改后的原生SQL查询
使用LEFT JOIN确保即使没有上传头像的用户也能被正常返回:
SELECT u.id as user_id, p.name, ab.key as avatar_key, ab.filename as avatar_filename FROM users as u JOIN profiles as p ON u.id = p.user_id LEFT JOIN active_storage_attachments asa ON asa.record_id = p.id AND asa.record_type = 'Profile' AND asa.name = 'avatar' LEFT JOIN active_storage_blobs ab ON asa.blob_id = ab.id WHERE u.department_id = 1
生成完整头像URL
直接在SQL中拼接URL不够灵活(不同存储服务如本地磁盘、S3的URL结构存在差异),推荐在Ruby层面用Rails内置方法生成标准URL:
users = User.find_by_sql(sql) result = users.map do |user| { user_id: user.user_id, name: user.name, avatar_url: user.avatar_key ? Rails.application.routes.url_helpers.rails_blob_url(user.avatar_key, only_path: false) : nil } end.to_json
关键关联逻辑说明
active_storage_attachments通过三个条件与profiles表关联:record_id对应profile的ID、record_type固定为模型名Profile、name对应附件字段名avataractive_storage_blobs通过blob_id与active_storage_attachments关联,获取文件的唯一key- 使用
LEFT JOIN而非JOIN,避免过滤掉未上传头像的用户记录
替代方案(Rails关联查询)
如果不想写原生SQL,也可以用Rails的查询接口实现相同效果,更符合框架风格:
users = User.joins(:profile) .left_joins(profile: { avatar_attachment: :blob }) .where(department_id: 1) .select( 'users.id as user_id', 'profiles.name', 'active_storage_blobs.key as avatar_key' ) result = users.map do |user| { user_id: user.user_id, name: user.name, avatar_url: user.avatar_key ? Rails.application.routes.url_helpers.rails_blob_url(user.avatar_key, only_path: false) : nil } end.to_json
内容的提问来源于stack exchange,提问作者Sylar
相关产品推荐
相关产品推荐

