Rails 7中如何筛选排除当前用户自有及已申请的项目列表
筛选用户未创建且未申请的项目列表
你的问题出在使用joins(:applicants)进行内连接,这会自动过滤掉没有任何申请者的项目,而且后续的where.not(applicants: {user_id: current_user.id})逻辑有误——只要项目存在其他申请者,即使你已经申请过,这个项目也会被错误地保留下来。
下面是几种正确的实现方式:
方法1:子查询排除已申请项目ID(直观易读)
先获取当前用户已申请的所有项目ID,再从候选列表中排除这些ID:
# 获取当前用户已申请的项目ID集合 applied_project_ids = current_user.applicants.pluck(:project_id) # 筛选条件:不是自己创建的 + 未申请过的项目 @sugested_projects = Project.where.not(user_id: current_user.id) .where.not(id: applied_project_ids)
这个方法逻辑清晰,适合数据量不大的场景,不需要复杂的SQL语法。
方法2:使用左外连接(Left Join)+ 去重
通过left_joins保留所有非用户创建的项目,再筛选出「无申请者」或「申请者不是当前用户」的项目,最后去重避免重复结果:
@sugested_projects = Project.where.not(user_id: current_user.id) .left_joins(:applicants) .where("applicants.user_id != ? OR applicants.id IS NULL", current_user.id) .distinct
left_joins会返回所有符合条件的Project,即使没有对应的Applicant记录;distinct用于消除同一项目因多个申请者产生的重复行。
方法3:NOT EXISTS子查询(高效适合大数据量)
直接在数据库层面用子查询判断当前用户是否申请过该项目,避免加载大量ID到内存,性能更优:
@sugested_projects = Project.where.not(user_id: current_user.id) .where.not( id: Applicant.select(:project_id).where(user_id: current_user.id) )
等价于SQL中的NOT EXISTS逻辑,数据库会高效处理这种关联查询,适合项目和申请者数据较多的场景。
内容的提问来源于stack exchange,提问作者Frub
相关产品推荐
相关产品推荐

