0

I have an array of images that I want to shuffle and only show the first ten results. I am having trouble figuring out how to do that.

Here is my code

<% @images.each.shuffle do |image| %>
  <tr>
    <td><%= image.name %></td>
    <td> <%= image_tag image.picture.url %></td>
    <td><%= image.likes %></td>
    <td><%= link_to 'Show', image %></td>
    <td><%= link_to 'Edit', edit_image_path(image) %></td>
    <td><%= link_to 'Destroy', image, method: :delete, data: { confirm: 'Are you sure?' } %></td>
  </tr>
<% end %>
Aaron
  • 4,380
  • 19
  • 85
  • 141
  • Is `@images` an AR proxy object or something? If so, you might want to adjust your query so that it does the shuffle-and-limit DB-side. ie, `@images = Image.where(...).order("rand()").limit(10)`. Note that sorting by random can't use indexes, but it's better than loading the whole table into RAM app-side. This has the added benefit of keeping logic out of your views, which is a Rails best practice. – Chris Heald Nov 28 '16 at 18:24
  • @ChrisHeald, thanks. I had to do a little digging but I found the answer on the DB side. Post you answer so I can give you credit – Aaron Nov 28 '16 at 22:25

2 Answers2

2

You can use sample function in the Array class.

<% @images.to_a.sample(10) do |image| %>
Du D.
  • 5,062
  • 2
  • 29
  • 34
1

If @images an AR proxy object or the result of some other DB query, you might want to adjust your query so that it does the shuffle-and-limit DB-side:

@images = Image.where(...).order("rand()").limit(10)

Note that sorting by random can't use indexes, but it's better than loading the whole table into RAM app-side. Something like this:

@images = Image.where(...)
@images.to_a.sample(10)

will load the results of the entire query into RAM in the Rails app, which will be quite slow.

This has the added benefit of keeping logic out of your views, which is a Rails best practice.

(Posted as an answer per asker's request)

Chris Heald
  • 61,439
  • 10
  • 123
  • 137