This project is archived and is in readonly mode.
render_to_string :json (or :xml or :update) before render results in DoubleRenderError
-
Bob Lail
- Tag set to actioncontroller workaround doublerendererror render bug
Although abstract_controller/rendering.rb:91 would lead you to believe that
response_bodyis 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_bodyhas been written:def index test = render_to_string(:template => "main/index") Rails.logger.info response_body # ... endBecause
response_bodyis 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 endbut 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 endThat should serve as a workaround for now.
-
Neeraj Singh
- 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 endI would say that render_to_string should always ensure that response_body is set to nil. I have attached a patch and a test.
-
Neeraj Singh
LH did not attache my patch last time.
-
José Valim
Patch seems to be empty. Neeraj, just tell me the commit hash in your fork please. :)
-
José Valim
@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
LH is still not liking it . Here is the patch
https://github.com/neerajdotname/rails/commit/fea223330ca8a5887b01c...
-
José Valim
Neeraj, do we need to manipulate the instance variable directly? Couldn't we simply call self.response_body = nil?
-
Neeraj Singh
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_bodyI 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
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
We could also change this file to properly handle nil. Wdyt?
-
Neeraj Singh
Here is an improved version.
https://github.com/neerajdotname/rails/compare/master...t_5875app
-
Bob Lail
(oops. Good call, José.)
-
Bob Lail
(oops. Good call, José.)
