2017-04-09 87 views
1

作为一个例子,假设我有这三个表: 事件,出勤(加入表)和用户。ActiveRecord查询所有关联包括

Event has_many attendances and has_many users through attendances 
User has_many attendances and has_many events through attendances 
Attendance belongs_to attendance and belongs_to user 

我希望能够查询所有事件以查找x个用户都参加了哪里。 作为一个例子:

Event  | Users who attended Event 
1    [1, 3, 4, 6, 9] 
2    [1, 4, 9] 
3    [3, 4, 6] 
4    [2, 3, 6] 

我想说 Event.by_attendended_users(user_4, user_9)并获得 Events: [1, 2]

我想沿着joins(:attendances).where("attendances.user_id IN :user_ids")或类似的东西线的东西,但还没有完全得到它的工作根据需要然而。任何帮助或反馈非常感谢!

编辑:作为一些额外的细节,正如@AbM指出的,如果加入一次只有2个用户,有一点可以用来查找用户的黑客。解决方案不起作用,因为查询的第二部分覆盖了第一部分。

理想情况下,应该能够在任意数量的协会工作,但最起码​​的要求,只是说,它需要使用2(现在)

此外,我希望能够使用这个作为范围,这意味着它可以链接到其他范围进一步过滤。 @AbM的解决方案只有在其他过滤器的链中首先调用该范围时才能使用该解决方案。

+0

@AbM - 非常聪明!理想情况下,我想解释一个使用超过2个用户的情况,但这仅仅是最低要求,所以如果没有更好的解决方案,我会很乐意使用这个。 :) 谢谢! – Rockster160

+0

这似乎没有工作。我认为'where(参加者:{user_id:user_9.id})'覆盖了初始范围并且重新回到原始问题。 :( – Rockster160

回答

0
user_ids = [1, 3, 5] 
events = Event.joins(:attendances) 
user_ids.each {|user_id| events = events.where('attendances.user_id = ?', user_id) } 

# events now contains all events where all specified users attended 
1
user_ids = [4, 9] 
events = Event 
user_ids {|user_id| events = events.where(id: Event.joins(:attendances).where(attendances: {user_id: user_id})) } 
events 

你可以做的另一种方法是使用自定义计算:

user_ids = [4, 9] 
Event.joins(:attendances).having('COUNT(CASE WHEN attendances.user_id IN (?) THEN 1 END) = ?', user_ids, user_ids.length).group(:id) 
+0

这不允许一个用户多次出席同一个事件,因为搜索结果会被计数混淆,但这是一个很好的开始,我可以使用常规数组操作手动完成其余部分。 – Rockster160

+0

我不太清楚你的意思,为什么一个用户会有多次参加同一个活动? – AbM