Rails render partial in a loop
Asked Answered
G

6

7

I am new to rails and I am trying to render a partial within a loop as such.

Here , books is an array eager loaded in controller.

 books.each do |book|
   <%= render 'books/book', :book => book %>
 end

This works fine. But when the books array is really huge, it takes time for the view to load completely. Is there any other efficient way using which the same can be achieved?. I tried partial with collection(like here) as well, but even that did not make much difference in the load time of books. Any suggestions would be highly appreciated. Thanks.

Gist answered 15/2, 2015 at 8:38 Comment(1)
Post the content of the partial. It's likely the performance issue is caused by something inside the partial.Intake
G
3

Rendering partial in a loop consume too much time because of open/close partial file every iteration. Instead of partial try to use your own helper for this purpose.

Gibb answered 30/3, 2015 at 18:1 Comment(0)
P
1

If you have list of values to display in the same view then you can iterate the values in the same view instead of rendering a new partial each time. If it's not the case then it is better to pass values from controller to your view. Hope it helps.

Pathoneurosis answered 15/2, 2015 at 8:49 Comment(1)
Rendering a plain partial, especially if you pass a collection, generally adds an overhead of a few milliseconds. That's not the issue (or nobody would ever use partials).Intake
W
1

I recently worked on a project in which I needed to render a table with about 1000 rows and I obviously experienced performance issues.

When pagination cannot be applied (due to requirements) and speed is required, then helpers is the solution (as already answered by Dima Melnik).

To prove what i said, i give a link to a performance test produced by Ben Scofield: http://viget.com/extend/helpers-vs-partials-a-performance-question

Woeful answered 21/7, 2015 at 15:3 Comment(0)
S
1

How about using "proc" on your view top, and then call it in your loop.

<% book_proc = proc do |book| %>
  #your html call
  <% nil %><%# return nil to prevent print out in last string %>
<% end %>

<% books.each do |book| %>
  <%= book_proc.call(book) %>
<% end %>
Sparse answered 17/2, 2019 at 6:23 Comment(0)
D
1

To summarize what I found, the helper is the way to go, as Dima Melnik succintly said. For instance, in your case, you could write a helper like this:

module BooksHelper # Or ApplicationHelper to be used globally

   def helper_render_book(book)
     # Insert partial's content here
   end

end

and then use it like this:

books.each do |book|
   <%= helper_render_book(book) %>
end

I was using partials like you, and having the same problem. I was listing about 300 students, and it felt slow. The view was taking around 2500 ms. I thought it was the amount of filesystem operations (altough they surely are cached), and tried reading the partial into a variable (outside the loop) and then doing an inline render in the loop:

<%= render inline: partial_content, locals: {student: student} %>

With this change, the view was taking around 2000 ms. And then, I tried inserting the contents of the partial into a helper, like I suggest. It's not very elegant, it doesn't feel like The Rails Way, but it took the view rendering to around 1600 ms, so it's better for performance.

Dictatorial answered 25/4 at 15:39 Comment(0)
P
0

You write that you're new to ruby/rails, so have you ever tried using pagination to solve your performance-problem?

A pagination will split your list into parts of e.g. 20 books and sets a paginator mostly at the bottom of your table.

Pycnidium answered 2/5, 2015 at 8:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.