Reputation: 1505
My models: User, Group, GroupsUser, and Availability.
I want to find all Availabilities created by users who are associated to a group, or several groups.
class Availability < ApplicationRecord
belongs_to :user
end
class User < ApplicationRecord
has_many :group_users
has_many :groups, through: :group_users
has_many :availabilities
end
class Group < ApplicationRecord
has_many :group_users
has_many :users, through: :group_users
end
class GroupUser < ApplicationRecord
belongs_to :group
belongs_to :user
end
Here is what I've tried to find all Availabilities created by a user in the same group as the first user. How can I make this query?
user = User.first
Availability.joins(:user).where('user.groups.pluck[:id] IN (?)', user.groups.pluck[:id])
Would also be great to put a scope on the Group, but it throws an error each time I do that.
Upvotes: 3
Views: 244
Reputation: 1677
Does this get what you're looking for?
class Availability < ApplicationRecord
belongs_to :user
has_many :groups, through: :user
scope :for_user_in_groups, lambda { |user|
next all unless user.present?
joins(user: :groups).where(groups: { id: user.groups.select(:id) }).distinct
}
end
This produces:
[32] pry(main)> Availability.for_user_in_groups(User.find(2))
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2 [["id", 2], ["LIMIT", 1]]
Availability Load (0.8ms) SELECT DISTINCT "availabilities".* FROM "availabilities" INNER JOIN "users" ON "users"."id" = "availabilities"."user_id" INNER JOIN "group_users" ON "group_users"."user_id" = "users"."id" INNER JOIN "groups" ON "groups"."id" = "group_users"."group_id" WHERE "groups"."id" IN (SELECT "groups"."id" FROM "groups" INNER JOIN "group_users" ON "groups"."id" = "group_users"."group_id" WHERE "group_users"."user_id" = $1) [["user_id", 2]]
=> [#<Availability:0x00007fd3830bae38 id: 6, user_id: 3>,
#<Availability:0x00007fd3830bacf8 id: 5, user_id: 2>,
#<Availability:0x00007fd3830babb8 id: 3, user_id: 3>,
#<Availability:0x00007fd3830baa78 id: 2, user_id: 2>]
Upvotes: 0
Reputation: 643
There are two options to do so:
1) Through the join
Availability.joins(user: :groups).distinct
2) Through the sub queries
Availability.where(user_id: User.joins(:groups).distinct.pluck(:id))
If you need to filter Availability with a specific group you can add .where(groups: { name: 'Group name' })
condition
Upvotes: 1