Search code examples
ruby-on-rails

How do I render a view with partials when Rails only wants to call render once?


In a controller action, I want to respond to a POST request with some JSON. Some of the JSON is rendered HTML. There are other important fields in the JSON, so I am rendering the template manually like this:

html = File.open('app/views/shared/_my_partial.html.erb').read
template = ERB.new(html)

html = template.result(binding)

render json: {status: 'OK', html: html, other_important_stuff: foo}

However, this means that I can't use any partials in the _my_partial.html.erb, like this:

<%= render partial: 'shared/my_inner_partial', locals: {var: var}

...because this provokes the error "(Render and/or redirect were called multiple times in this action".

What is the right approach here? I'd like to render a partial with the ability to render other nested partials inside. However I would like to send this to the client as part of a JSON response, with other fields in it which I need to set in the controller action.


Solution

  • DoubleRenderError happens when you call controller render method multiple times, which is different from a view render helper. But because you're using ERB directly and binding to a controller you end up calling controller render twice.

    The best option would be to create a dedicated template for your action and compose everything inside of it.

    There is also render_to_string if you really need to render multiple things in a controller:

    render json: {
      status: "OK",
      html: render_to_string(partial: "shared/my_partial"),
      other_important_stuff: foo
    }