Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Rails 3, how does one render HTML within a JSON response?

I'm porting an application from Merb 1.1 / 1.8.7 to Rails 3 (beta) / 1.9.1 that uses JSON responses containing HTML fragments, e.g., a JSON container specifying an update, on a user record, and the updated user row looks like . In Merb, since whatever a controller method returns is given to the client, one can put together a Hash, assign a rendered partial to one of the keys and return hash.to_json (though that certainly may not be the best way.) In Rails, it seems that to get data back to the client one must use render and render can only be called once, so rendering the hash to json won't work because of the partial render.

From reading around, it seems one could put that data into a JSON .erb view file, with <%= render partial %> in and render that. Is there a Rails-way of solving this problem (return JSON containing one or more HTML fragments) other than that?

In Merb:
controller:

only_provides :json
...
self.status = 204 # or appropriate if not async
return {
    'action' => 'update',
      'type' => 'user',
        'id' => @user.id,
      'html' => partial('user_row', format: :html, user: @user)
}.to_json

In Rails:
controller:

respond_to do |format|
  format.json do
    render template: '/json/message-1', 
      locals: { 
        action: 'update',
        type: 'user',
        id: @user.id,
        partial: 'user_row.html.erb', 
        locals: { user: @user }
      }
  end
end

view: json/message-1.json.erb

{
  "action": <%= raw action.to_json %>,
  "type": <%= raw type.to_json %>,
  "id": <%= raw id.to_json %>,
  "html": <%= raw render(partial: partial, locals: locals).to_json %>
}
like image 518
ylg Avatar asked Mar 17 '10 03:03

ylg


2 Answers

The closest to the original from Merb approach I could find in Rails is to use #render_to_string

render json: {
  'action' => 'update',
    'type' => 'user',
      'id' => @user.id,
    'html' => render_to_string(partial: 'user_row.html.erb', locals: { user: @user })
}

This gets around a fair bit of complexity that comes in from adding a layer of json.erb templates into the mix, whether it's Rails Purist approach I couldn't say; possibly something with RJS would typically be used.

like image 85
ylg Avatar answered Nov 17 '22 05:11

ylg


There's another question that has more solutions for json.erb files. See json erb template cannot find other html partial

like image 33
ajh Avatar answered Nov 17 '22 05:11

ajh