ActiveRecord查询包含所有关联

时间:2017-04-09 15:45:53

标签: ruby-on-rails postgresql 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个用户,那么可以用一些hack来查找用户。 解决方案不起作用,因为查询的第二部分覆盖了第一部分。

理想情况下,这应该能够处理任意数量的关联,尽管最低要求仅表示它需要使用2.(现在)

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

2 个答案:

答案 0 :(得分: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)

答案 1 :(得分: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