Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to render a view normally after using render_to_string?

In my Rails application I have an action which creates a XML document using an XML Builder template (rxml) template and render_to_string. The XML document is forwarded to a backend server.

After creating the XML document I want to send a normal HTML response to the browser, but somehow Rails is remembering the first call to render_to_string.

For example:

  • Rails cannot find the default view show.html.erb because it looks for a show.rxml.
  • Simply putting a render 'mycontroller/show.html.erb' at the bottom of my action handler makes Rails find the template, but the browser doesn't work because the response header's content type is text/xml.

Is there any way to use render_to_string without "tainting" the actual browser response?

EDIT: It seems that in Rails 2 erase_render_results would do the trick, but in Rails 3 it is no longer available.

like image 862
Daniel Rikowski Avatar asked Jan 13 '11 19:01

Daniel Rikowski


1 Answers

The pragmatic answer is that using a view file and two calls to render is Not The Rails Way: views are generally something that is sent to the client, and ActionPack is engineered to work that way.

That said, there's an easy way to achieve what you're trying to do. Rather than using ActionView, you could use Builder::XmlMarkup directly to generate your XML as a string:

def action_in_controller
  buffer = ""
  xml = Builder::XmlMarkup.new(buffer)

  # build your XML - essentially copy your view.xml.builder file here 
  xml.element("value")
  xml.element("value")

  # send the contents of buffer to your 3rd server

  # allow your controller to render your view normally
end

Have a look at the Builder documentation to see how it works.

The other feature of Builder that you can take advantage of is the fact that XML content is appended to the buffer using <<, so any IO stream can be used. Depending how you're sending content to the other server, you could wrap it all up quite nicely.

Of course, this could end up very messy and long, which is why you'd want to encapsulate this bit of functionality in another class, or as a method in your model.

like image 164
dnch Avatar answered Sep 27 '22 18:09

dnch