代码之家  ›  专栏  ›  技术社区  ›  Vincent

“拆分”ActiveRecord集合

  •  4
  • Vincent  · 技术社区  · 14 年前

    假设我有两个模型Post和Category:

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

    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]
    

    换句话说,通过所选类别id将所有帖子的集合“拆分”到数组中

    4 回复  |  直到 14 年前
        1
  •  13
  •   Harish Shetty    8 年前

    试试这个 group_by 功能开启 Array 班级:

    posts.group_by(&:category_id)
    

    参考API documentation

    警告:

    当潜在的数据集可能很大时,不应该在Ruby代码中执行分组。我使用 当最大可能的数据集大小为<1000在你的情况下,你可能有1000个 Post

    下面是一种方法(类似的解决方案由 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
    
        2
  •  0
  •   user393377    14 年前

    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
    
        3
  •  0
  •   nas    14 年前

    与其获取所有的帖子,然后对它们进行一些操作来对它们进行分类,这是一个有点性能密集型的练习,我更愿意像这样使用急切加载

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

    p = Array.new
    categories.each do |category| 
      p[1] = category.posts
      # do anything with p[1] array of posts for the category
    end
    
        4
  •  0
  •   bjg    14 年前

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