【问题标题】:ActiveRecord join through two associationsActiveRecord 通过两个关联加入
【发布时间】:2019-12-31 18:40:26
【问题描述】:

如果存在两种可能的关联,我如何获得包含特定 User 存在的所有唯一 Jobs 的 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)

有什么建议吗?

【问题讨论】:

  • 你的代码中有一个简单的错字:最后你写了.where("a.job_id = ? OR e.job_id = ?", userid, userid),当然应该是.where("a.user_id = ? OR e.user_id = ?", userid, userid)。但不确定使用两个内连接时查询是否有效?
  • 啊,很好,但这只是在这里重新输入的一个错字。我会更新我的帖子!

标签: ruby-on-rails join rails-activerecord


【解决方案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 

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

【讨论】:

    猜你喜欢
    • 2013-01-03
    • 2020-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多