4

I have a partial that I'm rendering twice on the same page, but in two different locations (one is shown during standard layout, one is shown during mobile/tablet layout).

The partial is rendered exactly the same in both places, so I'd like to speed it up by storing it as a variable if possible; the partial makes an API call each time, and the 2nd call is completely unnecessary since it's a duplicate of the first API call.

Is there any way to store the HTML from the returned partial as a variable and then use that for both renders?

Edit: I'm hoping to do this without caching, as it is a very simple need and I'm looking to keep the codebase lean and readable. Is it possible to store the partial as a string variable and then reference that twice?

2
  • 1
    Have you consider just using fragment caching (api.rubyonrails.org/classes/ActionController/Caching/…). If you are caching the same fragment, the cache call will stop the execution from occurring twice. Commented Jul 19, 2012 at 3:19
  • Hi Rob, see my edit above; I'm hoping to do this without caching if possible Commented Jul 19, 2012 at 5:44

3 Answers 3

8
<% content_for :example do %>
  <%= render :your_partial %>
<%end%>

then call <%= yield :example %> or <%= content_for :example %> wherever you want your partial called.

Sign up to request clarification or add additional context in comments.

1 Comment

Calling yield twice will not make the API call twice?
6

One option would be to use fragment caching. After you wrap the partial with a cache block, the second call should show the cached version of the first. For example:

<% cache do %>
  <%= render(:partial => 'my_partial') %>
<% end %>

... later in the same view ...

<% cache do %>
  <%= render(:partial => 'my_partial') %>
<% end %>

To store the result of the render to a string, you could try the render_to_string method of AbstractController. The arguments are the same as for render.

partial_string = render_to_string(:partial => 'my_partial')

4 Comments

I am familiar with fragment caching, but hoping to do this in a much simpler way (no need for sweepers, etc). The end HTML from the partial could be captured as a string variable and then simply rendered twice as such.
I added another way if you want to take a look.
This works in the controller [ render_to_string(:partial => 'my_partial', :locals => {:my_object => my_value}) ], but it takes about twice as long as simply making the API call twice and rendering twice. Any idea why?
Just basing it on the rough 200 OK times for 5-10 requests in development mode. Render request is taking ~750ms, while render_to_string is taking ~1500ms. Is there additional overhead when invoking AbstractController?
1

I'm adding an answer to this old question because it topped Google for a search I just made.

There's another way to do this now (for quite a while), the capture helper.

<% reuse_my_partial = capture do %>
  <%= render partial: "your_partial" %>
<% end %>

<div class="visible-on-desktop"
  <%= reuse_my_partial %>
</div>

<div class="visible-on-mobile"
  <%= reuse_my_partial %>
</div>

This is simpler and slightly safer than using content_for because there is no global storage involved that something else might modify.

The rails docs linked to use instance @vars instead of local vars because they want it to be available to their layout template. That's a detail you do not need to worry about, because you're using it in the same template file.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.