如何在Rails的多个Class数组中给某些值一个顺序?

时间:2019-01-14 15:12:06

标签: ruby-on-rails ruby postgresql

我有一个由多个Class对象组成的数组,按shuffle排序:

@streams = (Product.all + List.all + Post.all).shuffle

在供稿页面(如Facebook上的时间轴页面)中,对象的内容用.each显示,并且在每个Class上,都应用了特定的部分:

@streams.each do |stream|
  <% if stream.is_a?(Product) %>
   <%= render 'product_partial', object: stream %>
  <% elsif stream.is_a?(List) %>
   <%= render 'list_partial', object: stream %>
  <% end %>
 <% end %>

目标:因为应用程序中有很多产品(例如:200个),而帖子(100个)更少,列表(10个)更少,所以我想对每个内容(类)下达命令。这样,帖子和列表就不会淹没在产品上。

在一句话中:对于20种产品,显示2个帖子,1个列表。

有什么想法吗? 非常感谢。

2 个答案:

答案 0 :(得分:3)

我将使用概率和本机红宝石枚举器:

@streams =
  [Product, List, Post].map(&:all).map(&:shuffle)

type =
  case rand 23
  when 0..19 then 0
  when 20..21 then 1
  else 2
  end

@streams[type].pop # pop one element from the respective array

这有一个缺点,一种类型可能先于其他类型而结束,并且您可能需要显式检查并使用 still nothausted 类型,但它似乎比显式的1-per更好。 -2-per-20,因为它在某种程度上仍具有伪随机顺序。

答案 1 :(得分:2)

您可以执行以下操作:

@streams = custom_order(Products.all, Lists.all, Posts.all)

def custom_order(products, lists, posts)
  products_blocks = products.in_groups_of(20, false)
  lists_blocks = lists.in_groups_of(2, false)
  posts_blocks = posts.in_groups_of(1, false)

  result = []

  biggest_array = [products_blocks.length, lists_blocks.length, posts_blocks.length].max

  1.upto(biggest_array) do |_|
    # here we're pushing the blocks, result will be something like [[product, product .. product] [list, list] [posts]]
    result << products_blocks.shift
    result << lists_blocks.shift
    result << posts_blocks.shift
    # is ok if one of the blocks is nil, we'll use compact later
  end

  # result => [[product product product] [list list] [post] [product product] [list] nil]
  # compact to remove the nils
  # result => [[product product product] [list list] [post] [product product] [list]]
  # after flatten
  # result => [product product product list list post product product list]
  result.compact.flatten
end

编辑:更改了紧凑和扁平化