This project is archived and is in readonly mode.
render_to_string :json (or :xml or :update) before render results in DoubleRenderError
Reported by aduffeck | October 28th, 2010 @ 01:22 PM | in 3.x
In Rails3 render_to_string :json => ... (and :xml and :udpate) alters the response_body and thus makes subsequent render calls raise a DoubleRenderError
The following example works in Rails 2.3.8 but doesn't in Rails 3.0.1
class TestController < ApplicationController
def test
render :text => render_to_string(:json => "[]")
end
end
Comments and changes to this ticket
-
Jeff Kreeftmeijer November 1st, 2010 @ 05:03 PM
- Importance changed from to Low
Automatic cleanup of spam.
-
Bob Lail December 30th, 2010 @ 08:31 PM
- Tag set to actioncontroller workaround doublerendererror render bug
Although abstract_controller/rendering.rb:91 would lead you to believe that
response_body
is only set when you callrender
(and not when you callrender_to_string
), that isn't the case in Rails 3.0.3. If you try an experiment along the following lines, you'll see thatresponse_body
has been written:def index test = render_to_string(:template => "main/index") Rails.logger.info response_body # ... end
Because
response_body
is not nil, action_controller/metal/rendering.rb:16 raisesAbstractController::DoubleRenderError
. You'd think that you can refactor your example like this:class TestController < ApplicationController def test json = render_to_string(:json => "[]") response_body = nil render :text => json end end
but there's a catch. There's a second response_body accessor! It's in abstract_controller/base.rb:14. So what you'd actually write is:
class TestController < ApplicationController def test json = render_to_string(:json => "[]") @_response_body = nil render :text => json end end
That should serve as a workaround for now.
-
Neeraj Singh January 21st, 2011 @ 07:21 PM
- State changed from new to open
- Milestone set to 3.x
- Tag changed from actioncontroller workaround doublerendererror render bug to actioncontroller workaround doublerendererror render bug, patched
- Assigned user set to José Valim
This is an edge case. You will run into this error only if you are using
render_to_string(:json => '') render_to_string(:xml => '') render_to_string(:js => '')
That is because of following code
add :json do |json, options| json = json.to_json(options) unless json.kind_of?(String) json = "#{options[:callback]}(#{json})" unless options[:callback].blank? self.content_type ||= Mime::JSON self.response_body = json end add :js do |js, options| self.content_type ||= Mime::JS self.response_body = js.respond_to?(:to_js) ? js.to_js(options) : js end add :xml do |xml, options| self.content_type ||= Mime::XML self.response_body = xml.respond_to?(:to_xml) ? xml.to_xml(options) : xml end
I would say that render_to_string should always ensure that response_body is set to nil. I have attached a patch and a test.
-
José Valim January 21st, 2011 @ 07:24 PM
Patch seems to be empty. Neeraj, just tell me the commit hash in your fork please. :)
-
José Valim January 21st, 2011 @ 07:25 PM
@BobLail, your first response_body does not work because you are creating a local variable instead of calling a method. "self.response_body = nil" should do the trick.
-
Neeraj Singh January 21st, 2011 @ 07:26 PM
LH is still not liking it . Here is the patch
https://github.com/neerajdotname/rails/commit/fea223330ca8a5887b01c...
-
José Valim January 21st, 2011 @ 07:34 PM
Neeraj, do we need to manipulate the instance variable directly? Couldn't we simply call self.response_body = nil?
-
Neeraj Singh January 21st, 2011 @ 08:05 PM
My tests were failing with setting self.response_body = nil
def render_to_string ..... self.response_body = nil end #/metal/rendering.rb puts response_body #=> [nil] raise ::AbstractController::DoubleRenderError if response_body
I did not dig into why it is this way. It worked with @_response_body = nil and I left it. Guess I was being lazy.
Will look into it later.
-
Neeraj Singh January 21st, 2011 @ 08:49 PM
Setting self.response_body = nil become [ nil ] because of this line of code
# action_controller/metal.rb def response_body=(val) body = val.respond_to?(:each) ? val : [val] super body end
-
José Valim January 21st, 2011 @ 09:46 PM
We could also change this file to properly handle nil. Wdyt?
-
Neeraj Singh January 22nd, 2011 @ 12:24 AM
Here is an improved version.
https://github.com/neerajdotname/rails/compare/master...t_5875app
-
José Valim January 25th, 2011 @ 07:14 PM
- State changed from open to resolved
Applied, thanks Neeraj!
Create your profile
Help contribute to this project by taking a few moments to create your personal profile. Create your profile »
<h2 style="font-size: 14px">Tickets have moved to Github</h2>
The new ticket tracker is available at <a href="https://github.com/rails/rails/issues">https://github.com/rails/rails/issues</a>