I have an action where I do a render_to_string and then a final render
is done to send data back from the action. Here’s the action:
File.open(pdfgen.xfdf_file, "w") do |f|
f.write(render_to_string(:layout => false))
return display_popup_error #The 'display_popup_error' does a
render(:text => url_for(:action => 'render_pdf', :filename =>
This works fine. I have another action that is basically the same, but
I get a double render error with that action. The difference between
the two actions is that in the one above, I am certain that the
render_to_string call completes.
In the other action, I am certain that an error occurs during the
render_to_string call, (i.e. the render_to_string call doesn’t
Here’s a hypothesis: A call to render_to_string is marked internally as
one render and then at the end of it, that render count is reduced back
to 0 or cleared somehow. Therefore, a successful call to
render_to_string will allow a later call to render. However, if
render_to_string doesn’t complete, then the render “still counts” and
thus, a double render error if you try to do another render.
Anyone have any insight into the behavior of render_to_string followed
by a render that might explain what I’m seeing?
SOLUTION: It turns out that I was doing a redirect somewhere not obvious
before my rescue block was hit, and I wasn’t returning from the redirect
(like I should have been - so that’s a bug in my code).
MORE GOOD NEWS: In order to figure this out, I ended up sifting through
the guts of ActionController#Base, and I discovered that there are two
variables internally which track whether or not a render or redirect has
been performed. So my hypothesis was correct. In addition, there are
two protected methods (which means that we can call them !!!), called
erase_render_results and erase_redirect_results, which wipe away any
render or redirect flags that have been set. When I put
erase_redirect_results in my rescue block, everything worked fine.
So, if you know what you are doing, and you need to escape the “double
render” box that Rails puts you in, you can use these two methods to
“wipe the slate clean” on your own as you need to.
As it turns out, in my case, I should have been redirecting before I
ever even attempted the begin/rescue block so I need to fix that.
But, if my render_to_string call failed within the internal render,
so that erase_render_results didn’t get called internally, then a
mysterious double render error would show up.
Keep in mind that render_to_string doesn’t “count as a render” only if
it completes successfully.