Rails中如何获取含当前用户产品的全部分类(含无产品分类)?
解决分类关联当前用户产品并包含空分类的问题
嘿,我懂你的需求啦——要拿到所有分类,不管有没有当前用户的产品,同时每个分类只展示当前用户的产品对吧?之前的代码之所以漏了空分类,是因为where(products: { user_id: current_user.id })会触发内连接,自动过滤掉没有匹配产品的分类。下面给你几个简洁的解决方案:
方案一:左外连接+条件筛选(最直接)
直接用left_joins做左外连接保留所有分类,再筛选出符合条件的产品:
# 获取所有分类(包含当前用户产品或无产品的分类) @categories = Category.left_joins(:products) .where('products.user_id = ? OR products.id IS NULL', current_user.id) .distinct # 避免一个分类对应多个产品时返回重复行 # 转JSON时只保留当前用户的产品 @categories.as_json(include: { products: { conditions: { user_id: current_user.id } } })
关键说明:
left_joins(:products):左外连接语法,确保所有Category记录都被保留,哪怕没有对应的Productwhere条件:筛选出产品属于当前用户,或者根本没有产品的分类distinct:因为一个分类对应多个产品时,查询会返回多条重复的Category记录,用这个去重as_json里的conditions:保证最终JSON里只带当前用户的产品,不会混入其他用户的数据
方案二:Rails 6+专属优雅写法
如果你的Rails版本是6.0及以上,可以用where.missing快速定位无产品的分类,再和有当前用户产品的分类合并:
# 先在Category模型里定义可复用的作用域 class Category < ApplicationRecord has_many :products scope :with_user_products, ->(user) { includes(:products).where(products: { user_id: user.id }) .or(Category.where.missing(:products)) } end # 调用作用域获取目标数据 @categories = Category.with_user_products(current_user) @categories.as_json(include: { products: { conditions: { user_id: current_user.id } } })
关键说明:
where.missing(:products):Rails 6+新增的语法,专门用来查询没有关联products的分类,代码可读性拉满or:把"有当前用户产品的分类"和"无产品的分类"合并,直接得到所有符合需求的分类
最终效果验证
处理后得到的JSON结构会是这样:
[ { "id": 1, "name": "Category1", "products": [{"id":1, "name":"Product1", ...}, {"id":2, "name":"Product2", ...}] }, { "id": 2, "name": "Category2", "products": [{"id":3, "name":"Product1", ...}, {"id":4, "name":"Product2", ...}] }, { "id": 3, "name": "Category3", "products": [] } ]
完全匹配你要的展示效果:有产品的分类带对应产品,空分类的products数组为空,前端判断后显示(empty)即可。
内容的提问来源于stack exchange,提问作者Huzai
相关产品推荐
相关产品推荐

