如何交错多个ActiveRecord关联查询?

时间:2016-05-17 16:30:19

标签: ruby-on-rails ruby rails-activerecord ruby-on-rails-5

我有五个类别,每个类别约五个帖子。 E.g。

=> category_a.posts
=> #<Post id:01>, #<Post id:02>, #<Post id:03> etc

=> category_b.posts
=> #<Post id:10>, #<Post id:11>, #<Post id:12> etc

=> category_c.posts
=> #<Post id:20>, #<Post id:21>, #<Post id:22> etc

我喜欢一系列儿童,他们交错(尽可能均匀),即

#<Post id:01>, #<Post id:10>, #<Post id:20>, #<Post id:02>, #<Post id:11> etc

我怎么能做到这一点?

2 个答案:

答案 0 :(得分:2)

Dave Schweisguth的回答很好,可能会让您知道解决问题需要了解的内容。但是,该解决方案不允许您选择项目交错的顺序。这是一个有希望的更通用的解决方案:

def full_zip(*args)
  max_len = args.map(&:length).max
  ([nil] * max_len).zip(*args).flatten.compact
end

然后会像full_zip(category_a.posts, category_b.posts, category_c.posts)full_zip(*[cat_a, cat_z].map(&:posts))一样使用它。按照您希望的顺序使用类别。

编辑:这个问题的一个问题是,如果原始列表中有你想保留的nils。

答案 1 :(得分:1)

它只有五个查询和大约15个模型,所以在内存中这样做很好:

 posts =
   [category_a, category_b, category_c, category_d, category_e].
   map(&:posts)
   sort_by(&:length)
 posts.first.zip(*posts[1..-1]).flatten.compact

首先放置最长的数组会阻止zip在其参数中从数组中删除元素,这些元素的长度超过它所调用的数组。 compact会删除nil创建的zip,如果其参数中的数组长于它所调用的数组。