I have two types: blogs
and posts
. Post uses the closure_tree gem (an acts_as_tree
variant) to allow posts nested under posts. Also, each blog has_many
posts.
class Post < ActiveRecord::Base
acts_as_tree
end
Given a set of blogs (by the same author, say), I would like to get all the posts in those blogs as a scope (i.e., as an ActiveRecord::Relation not as an array).
Something like:
Blog.all_posts_by('john')
I have tried two things so far:
Approach #1, using arrays (not scopes), is as follows:
class Blog
has_many :posts
def self.all_posts_by author_name
self.where(author_name: author_name).map(&:posts).flatten.map(&:self_and_descendants).flatten
end
end
But I would like to have a scope, as the array map approach may not perform well with large data sets.
Approach #2: This approach yields a true scope, but using sql unions and sql strings:
class Blog
has_many :posts
def self.all_posts_by author_name
post_collections = []
Blog.where(author_name: author_name).each do |blog|
post_collections = blog.posts.map(&:self_and_descendants)
end
posts_sql = ""
post_collections.each do |post_collection|
posts_sql << "( #{post_collection.to_sql} ) union "
end
final_sql = posts_sql.chomp('union ')
result = Post.from("
(
#{final_sql}
) #{Post.table_name}
").distinct
end
end
This might work, but I am looking for a better way, hopefully using some available scope magic.