How do I return records associated to a list of children of a nested set?
Rails version 3.0.3, I am new to rails, but been in webdev for a long time.
I am using awesome nested set.
I have the tables "posts", "labels", and "labels_posts"
posts has_and_belongs_to_many labels
labels has_and_belongs_to_many postslabels acts_as_nested_set
I have a label_id and I want to get all posts that are associated to that label and its children, all as a single ordered result set.
Let us say that I have Labels: "L1, L1.1, L1.1.1, L1.2, L2"
Given L1, and knowing that therefore I h开发者_StackOverflowave L1, L1.1, L1.1.1, and L1.2, I would normally run the query:
select id, title
from posts
where exists (select * from labels_posts where labels_posts.post_id = posts.id and labels_posts.label_id IN ('L1', 'L1.1', 'L1.1.1', 'L1.2'))
order by created_at desc
This query would return all the posts associated with each of those labels.
So, what is the rails way to do this?
EDIT:
So, here is my controller
@label = Label.find(params[:label])
@posts = Post.all.select do |post|
post.label_ids.include?(@label.self_and_descendants.map(&:id))
end
And here is the rails server output
Label Load (0.5ms) SELECT "labels".* FROM "labels" WHERE ("labels"."cached_slug" = 'caribbean') LIMIT 1
Post Load (0.6ms) SELECT "posts".* FROM "posts"
Label Load (0.2ms) SELECT "labels".id FROM "labels" INNER JOIN "labels_posts" ON "labels".id = "labels_posts".label_id WHERE ("labels_posts".post_id = 1 )
Label Load (0.8ms) SELECT "labels".* FROM "labels" WHERE ("labels"."lft" >= 1 AND "labels"."rgt" <= 8) ORDER BY "lft"
Label Load (0.1ms) SELECT "labels".id FROM "labels" INNER JOIN "labels_posts" ON "labels".id = "labels_posts".label_id WHERE ("labels_posts".post_id = 2 )
CACHE (0.0ms) SELECT "labels".* FROM "labels" WHERE ("labels"."lft" >= 1 AND "labels"."rgt" <= 8) ORDER BY "lft"
I am not sure the select method is the one that is needed.
EDIT ANSWER:
So here is the answer I arrived at
@label = Label.find(params[:label])
@posts = Post.order('posts.created_at desc').where('labels_posts.label_id IN (?)', @label.self_and_descendants.map(&:id)).includes(:labels)
try
Post.all(:conditions => "id = labels_posts.post_id AND label_posts.label_id in('L1', 'L1.1', 'L1.1.1', 'L1.2')", :include => [:label => labels_posts], :order => :created_at)
Lets first collect the ids of the Label (label_id) and its children.
Then use the Ruby Array Select method to select those posts which are associated with the appropriate labels.
label_ids = Label.find(label_id).children.map(&:id).push(label_id)
posts = Post.all.select{|post| post.label_ids.include?(label_ids)}
精彩评论