Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

'Splitting' ActiveRecord collection

Let's say I have two models Post and Category:

class Post < ActiveRecord::Base
  belongs_to :category
end

class Category < ActiveRecord::Base
  has_many :posts
end

Is there a method that will allow me to do something like

posts = Post.find(:all)

p = Array.new

p[1] = posts.with_category_id(1)
p[2] = posts.with_category_id(2)
p[3] = posts.with_category_id(3)
...

or

p = posts.split_by_category_ids(1,2,3)

=> [posts_with_category_id_1, 
    posts_with_category_id_2,
    posts_with_category_id_3]

In other words, 'split' the collection of all posts into arrays by selected category ids

like image 732
Vincent Avatar asked Dec 12 '22 20:12

Vincent


1 Answers

Try the group_by function on Array class:

posts.group_by(&:category_id)

Refer to the API documentation for more details.

Caveat:

Grouping should not performed in the Ruby code when the potential dataset can be big. I use the group_by function when the max possible dataset size is < 1000. In your case, you might have 1000s of Posts. Processing such an array will put strain on your resources. Rely on the database to perform the grouping/sorting/aggregation etc.

Here is one way to do it(similar solution is suggested by nas)

# returns the categories with at least one post
# the posts associated with the category are pre-fetched
Category.all(:include => :posts, 
    :conditions => "posts.id IS NOT NULL").each do |cat| 
  cat.posts
end
like image 67
Harish Shetty Avatar answered Dec 27 '22 21:12

Harish Shetty