Lets say there are two models: User
and Post
where each post belongs to a user and a user can have many posts.
If you do @user.posts
you get all posts for @user
. But, given @users
, is there a more elegant way than Post.where(user_id: @users.map(&:id))
to get all posts for @users
? Something like @users.posts
?
Based on your comment that @users
is an ActiveRecord::Relation
, the simplest method is to let Active Record figure it out for you:
Post.where(user: @users)
# SELECT "posts".* FROM "posts" WHERE "posts"."user_id" IN
# (SELECT "user"."id" FROM "users")
This performs a single database query and lets the database do all the heavy lifting with a sub-select (your sub-select might look different... in my example @users
was simply User.all
).
For cases when you aren't using .map
to get an id field, you might want to consider .pluck
to return an array of values from the database without fetching entire records. For example:
@users.pluck(:name)
# instead of
@users.map(&:name)
In theory you can use .pluck
in your scenario but if you have a lot of users you'll generate and send a very long SQL query containing an array of user IDs instead of letting the database do the work itself...
Post.where(user_id: @users.pluck(:id))
# SELECT "posts".* FROM "posts" WHERE "posts"."user_id" IN
# (2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 64, 65, 66, 67, 68, 69, 70, 72, 73, 71, 74, 75, 76, 77, 78, 79, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 98, 99, 100, 101, 102, 103, 97)