ActiveRecord通过两个关联加入

问题描述 投票:0回答:1

鉴于存在两种可能的关联,如何获得具有特定Jobs的所有唯一User的ActiveRecord集合?

class User
 has_many :assignments
 has_many :jobs, through: assignments
 has_many :events
 has_many :jobs_via_events, through: :events, source: :jobs
end
class Assignment
 belongs_to :user
 belongs_to :job
end
class Event
 belongs_to :user
 belongs_to :job
end
class Job
 has_many :assignments
 has_many :events
end

到目前为止,我所能想到的最好的方法是使用多个联接,但是并没有得到正确的结果:

Job.joins("INNER JOIN assignments a ON jobs.id = a.job_id").joins("INNER JOIN events e ON jobs.id = e.job_id").where("a.user_id = ? OR e.user_id = ?", userid, userid)

有什么建议吗?

ruby-on-rails join rails-activerecord
1个回答
1
投票

一种简单的方法是先收集所有作业ID,然后获取这些ID的所有作业。

我们首先要求用户提供所有工作ID的数组:

event_job_ids = Event.where(user_id: user).select(:job_id).map(&:job_id) 
assignment_job_ids = Assignment.where(user_id: user).select(:job_id).map(&:job_id) 
all_job_ids = (event_job_ids + assignment_job_ids).uniq  

请注意,根据您使用的rails版本,最好将select(:job_id).map(&:job_id)替换为.pluck(:job_id)(这应该更有效,但是select.map

然后获得组装ID的作业非常简单:

 jobs = Job.where(id: all_job_ids)

这是一种幼稚的方法,我们如何批准呢?如果我要写查询,我会写类似下面的内容

 select * from jobs 
 where id in (
   select job_id from assignments where user_id=#{user_id}
   union
   select job_id from events where user_id=#{user_id}
 )

那么我们如何将其转换为范围?

 class User

   def all_jobs 
     sql = <<-SQL
       select * from jobs 
       where id in (
         select job_id from assignments where user_id=#{self.id}
         union
         select job_id from events where user_id=#{self.id}
       )
     SQL  
     Job.find_by_sql(sql)
   end 

当然,这是未经测试的代码,但这应该可以帮助您入门吗?

© www.soinside.com 2019 - 2024. All rights reserved.