Collection "Splitting" ActiveRecord

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

class Post < ActiveRecord::Base belongs_to :category end class Category < ActiveRecord::Base has_many :posts end 

Is there a way that allows 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 messages into arrays with the selected category identifiers

+4
source share
4 answers

Try the group_by function in the Array class:

 posts.group_by(&:category_id) 

See the API for more details.

Protest:

Grouping should not be done in Ruby code when the potential data set can be large. I use the group_by function when the maximum size of the data set is <1000. In your case, you may have 1000 with Post s. Processing such an array will strain your resources. Rely on a database to do grouping / sorting / aggregation, etc.

Here is one way to do this (a 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 
+11
source

Of course, but given your relationship with the model, I think you need to look at it differently.

 p = [] 1.upto(some_limit) do |n| posts = Category.posts.find_by_id(n) p.push posts if posts end 
0
source

Something like this might work (Post instance method, untested):

 def split_by_categories(*ids) self.inject([]) do |arr, p| arr[p.category_id] ||= [] arr[p.category_id] << p if ids.include?(p.category_id) arr end.compact end 
0
source

Instead of receiving all the messages and then doing some operation on them to classify them, which is an intensive-intensity exercise, I prefer to use such a downloadable download

 categories = Category.all(:include => :posts) 

This will create a single sql query to retrieve all your posts and category objects. Then you can easily iterate over them:

 p = Array.new categories.each do |category| p[1] = category.posts # do anything with p[1] array of posts for the category end 
0
source

Source: https://habr.com/ru/post/1315865/


All Articles