If I have a collection of Post
s, is there anyway to get all Comment
s for all of those posts using method chaining or scopes?
For example:
posts = Post.where(published: true)
comments = posts.comments
# vs
comments = []
posts.each do |post|
comments.push(post.comments)
end
Sure, there are a few ways. You can can use map
and flatten
, which is fine for a small number of records. Make sure you load the comments in bulk by using includes
.
Post.where(published: true).includes(:comments).map(&:comments).flatten
Or you can use a join. This puts more work on the database, which is likely faster, but depends on your schema and dataset. You will typically want to use uniq
to prevent duplicates.
posts = Post.where(published: true)
Comment.joins(:post).merge(posts).uniq
Also, make sure that you fully qualify any explicit fragments in any clauses on joined tables, e.g. use where('posts.created_at < ?', ...)
instead of where('created_at < ?', ...)
.
Edit:
Another variant on the first, in case you want to return a relation (which can be further scoped down the line):
Comment.where(id: Post.where(published: true).pluck(:id))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With