Reputation: 34013
I have an unknown number of categories.
I want to pick one post from each category, and when there are no more categories I want to start from the beginning until I've reached a fixed number posts.
This is what I have, how could I rerun this iteration until I have my desired amount of posts?
desired_amount = 40
categories.each_with_index do |category, index|
post = category.posts.order(position: :asc)[index]
# do something with the post
return if desired_amount == (index + 1)
end
Upvotes: 0
Views: 73
Reputation: 1767
Personally, I would much prefer something like this:
posts = categories.cycle.take(desired_amount).each_with_index.map do |cat,ind|
cat.posts.order(position: :asc)[ind / categories.count]
end
That would give you the first post in each category, followed by the second post in each category, etc, until you had the number of posts you wanted. The one caveat is that if any category didn't have enough posts, your final array would have some empty spots in it (i.e. nils).
Upvotes: 1
Reputation: 6870
You could define an array of post before starting to loop:
desired_amount = 40
posts_array = []
unless posts_array.count == desired_amount
categories.each_with_index do |category, index|
post = category.posts.order(position: :asc)[index]
posts_array << post
return if desired_amount == (index + 1)
end
end
Upvotes: 0
Reputation: 1930
Maybe try something like this?
all_posts = []
#include posts to prevent constant querying the db
categories_with_posts = categories.includes(:posts)
until all_posts.size == 40
categories_with_posts.each do |category|
#pick a random post from current category posts
post = category.posts.order(position: :asc).sample
# add the post to collection if post is not nil
all_posts << post if post
# do something with the post
break if all_posts.size == 40
end
end
Upvotes: 0