33

I have X number of image objects that I need to loop through in a view and want to create a new div every 6 objects or so (for a gallery).

I have looked at cycle but it seems to change every other record. Does anyone know of a way to insert code into a view every 6 times?

I could probably do it with nested loops but I am kinda stumped on this one.

Arslan Ali
  • 17,418
  • 8
  • 58
  • 76
Dustin M.
  • 2,884
  • 3
  • 20
  • 18

2 Answers2

108

You can use Enumerable#each_slice in conjunction with #each to avoid inline calculations. each_slice breaks the array into chunks of n, in this case 6.

<% @images.each_slice(6) do |slice| -%>
  <div class="gallery">
    <% slice.each do |image| -%>
      <%= image_tag(image.url, :alt => image.alt) %>
    <% end -%>
  </div>
<% end -%>
thorncp
  • 3,587
  • 3
  • 24
  • 20
  • That seems like a more conventional way to do it.. I'll give a a try. – Dustin M. May 17 '10 at 19:29
  • Thanks Thorn, I prefer this method to keep my views clean. Thanks! – Dustin M. May 17 '10 at 19:34
  • 1
    Thanks, this works great. A lot more sexy than keeping a counter. – Mosselman Dec 20 '12 at 16:53
  • How would you handle this when using an interator that doesn't support this thing like @documents.each_hit_with_result in Solr? – tibbon Jan 10 '13 at 17:20
  • I haven't used Solr before, but I see that method returns an enumerable if no block is given (typical Ruby behavior). In that case, you should be able to just chain on top of it: `@documents.each_hit_with_result.each_slice(6) do |slice|`. Source: https://github.com/sunspot/sunspot/blob/master/sunspot/lib/sunspot/search/hit_enumerable.rb#L49 – thorncp Jan 14 '13 at 20:21
  • It works perfectly. But do you have any idea if we can find the index as well, I mean method each_slice with index as array ? – Shyamkkhadka Feb 19 '14 at 08:46
  • I got my answer myself. In fact, I found we can use each_slice_with index as well. – Shyamkkhadka Feb 19 '14 at 08:53
  • Whooa, this is so comfortable – IvRRimUm Mar 02 '17 at 15:28
14

This is a Ruby question. You can meld this into whatever your view is trying to do.

@list.each_with_index do |item, idx|
  if((idx + 1) % 6 == 0)
    # Poop out the div
  end
  # Do whatever needs to be done on each iteration here.
end
jdl
  • 17,702
  • 4
  • 51
  • 54
  • Great solution @jdl, this works perfect for injecting an ad partial into a looped list (which I had trouble figuring out in the past). – VegaStudios Oct 03 '18 at 01:09