rails 3 - How to render a PARTIAL as a Json response - ruby-on-rails

I want to do something like this:
class AttachmentsController < ApplicationController
def upload
render :json => { :attachmentPartial => render :partial => 'messages/attachment', :locals => { :message=> #message} }
end
Is there a way to do this? render a Partial inside a JSON object? thanks

This should work:
def upload
render :json => { :attachmentPartial => render_to_string('messages/_attachment', :layout => false, :locals => { :message => #message }) }
end
Notice the render_to_string and the underscore _ in before the name of the partial (because render_to_string doesn't expect a partial, hence the :layout => false too).
UPDATE
If you want to render html inside a json request for example, I suggest you add something like this in application_helper.rb:
# execute a block with a different format (ex: an html partial while in an ajax request)
def with_format(format, &block)
old_formats = formats
self.formats = [format]
block.call
self.formats = old_formats
nil
end
Then you can just do this in your method:
def upload
with_format :html do
#html_content = render_to_string partial: 'messages/_attachment', :locals => { :message => #message }
end
render :json => { :attachmentPartial => #html_content }
end

This question is a bit old, but I thought this might help some folks.
To render an html partial in a json response, you don't actually need the with_format helper as explained in mbillard's answer. You simply need to specify the format in the call to render_to_string, like formats: :html.
def upload
render json: {
attachmentPartial:
render_to_string(
partial: 'messages/attachment',
formats: :html,
layout: false,
locals: { message: #message }
)
}
end

In Rails 6 I think this might be a little different from the accepted answer. I don't think you need to set the underscore in the partial name. This worked for me:
format.json {
html_content = render_to_string(partial: 'admin/pages/content', locals: { page: #page }, layout: false, formats: [:html])
render json: { attachmentPartial: html_content }
}

Related

ActionController::UnknownFormat for json response

Im using this code in my controller to give json response
respond_to do |format|
msg = { :status => "ok", :message => "Success!" }
format.json { render :json => msg }
end
is giving me an error -> ActionController::UnknownFormat on the "respond_to do |format|" line.
In my routes.rb,
Im using this
get '/xyz' => 'xyzs#abc'
Try to do it like:
msg = { :status => "ok", :message => "Success!" }
render :json => msg
Please check whether JSON Mimetype is added to your config/initializers/mime_types.rb
Mime::Type.register "application/json", :json
Check if you have a class level respond_with call in your controller or in ApplicationController. If there is one, check if :json is passed as one of its params.

Want to have a partial update with ajax

I have a form:
<% form_tag({:controller => "/faq", :action => 'search_ajax'}, :update => "help_results", remote: true) do %>
that is going to the search_ajax action which is supposed to update the help_results div. That action is supposed to render a partial at the end, but I for sure am having syntax issues:
def search_ajax
#categories = HelpCategory.find(:all)
if params[:query].not_blank? && params[:query] != "Search for help about..."
#query = params[:query]
#terms = params[:query].split.map {|t| "%#{t.downcase}%" }
options = {
:allow_partial_match => true,
:order => 'fulltext_match_score DESC',
}
#results = SearchableText.search_model(HelpItem, #query, options).uniq
#results = {"Search Results" => #results} if !#results.blank?
#complicated_query = HelpItem.is_complicated_query?(#query)
#search_included = true
else
#results = HelpItem.all.group_by {|item| item.category.name rescue "Misc"}
#search_included = false
end
render :partial => "results"
respond_to do |format|
format.js do
render :partial => 'results'
end
format.html do
render :partial => 'results'
end
end
end
Some of the respond_to area is commented out. I am getting the error message:
ActionController::DoubleRenderError in FaqController#search_ajax
I know that if I add the remote => true helper into my form that the controller action needs to respond to js. I'm pretty sure this is a syntax error. The respond_to also comes at the end of my controller action.
Remove the
render :partial => "results"
Above the respond_to block

Rails and Active Model Serializers: prevent double JSON encoding and escape characters (\)

In one of my controllers I manually assemble my JSON data to be able to use AMS custom serializers:
data[:foos] = {}
Foo.find(foo_ids).each do |f|
data[:foos][f.id.to_s] = render_to_string :json => f, :root => false, :serializer => FooCustomSerializer
end
data[:moos] = {}
Moo.find(moo_ids).each do |f|
data[:moos][f.id.to_s] = render_to_string :json => f, :root => false, :serializer => MooCustomSerializer
end
result = {:system => system_info, :content => data}
respond_to do |format|
format.json { render json: result }
end
It works, but the problem is it encodes twice the Moos and Foos, and the JSON rendered has plenty of escaped characters:
{ "system":"OK",
"content":
"foos":"[{\"name\":\"Rex\",\"breed\":\"Lab\"},{\"name\":\"Spot\",\"breed\":\"Dalmation\"},{\"name\":\"Fido\",\"breed\":\"Terrier\"}]"
...
Is there a way to prevent this?
Just put .to_json after the hash variable.
Example:
format.json { render json: result }
# Change to
format.json { render json: result.to_json }

Ajax and vote_fu | missing before statement

relate question: Vote_fu and Ajax requests
There seems to be something wrong with my Ajax request.
What I 'm trying to do is on event click vote submit a vote then update page with out refreshing the page.
votes_controller.rb:
def create
#album = Album.find(params[:album_id])
respond_to do |format|
if current_user.vote(#album, params[:vote])
format.js { render :action => "create", :vote => #vote }
format.html { redirect_to([#album.user, #album]) }
#format.xml { render :xml => #album, :status => :created, :location => #album }
else
format.js { render :action => "error" }
format.html { render :action => "new" }
format.xml { render :xml => #vote.errors, :status => :unprocessable_entity }
end
end
end
link | for view album show :
<%= link_to_remote "Vote Up",
:url => user_album_votes_path(album.user, album,
:vote => :true, :format => :js),
:method => :post %>
application.js
jQuery.ajaxSetup({
'beforeSend': function(xhr) {xhr.setRequestHeader("Accept", "text/javascript")}
})
jQuery(document).ready(function() {
$("#votes_.album").bind('click');
})
create.js
page.replace_html "#votes_{#album.id}",
:partial => "album_vote",
:locals => {:album => #album}
This is the following error message which I'm getting:
missing ; before statement
[Break on this error] page.replace_html "#votes_#{#album.id}", ...bum_vote", :locals => {:album => #album}
I'm not sure what is going wrong here I have been following many example from the vote_fu doc's
still having problems.
http://github.com/peteonrails/vote_fu/tree#readme
one amendment made on create.js
there is now another error:
No the error has moved over to the votes_controller
NoMethodError (You have a nil object when you didn't expect it!
<br />
The error occurred while evaluating nil.vote):
app/controllers/votes_controller.rb:53:in `create'
app/controllers/votes_controller.rb:52:in `create'
<br />
Rendered rescues/_trace (128.4ms)
Rendered rescues/_request_and_response (0.4ms)
Rendering rescues/layout (internal_server_error)
These lines are on the create action, which looks perfectly fine!?
How do I get this to work?
Regard
Dan
Try changing the create.js to
page.replace_html "#votes_#{#album.id}", :partial => "album_vote", :locals => {:album => #album}
You might have missed the # for the variable string interpolation.
Solved!
The problem was that I didn't add a before statement to refresh the vote count!
so I did and it worked as well as that, I changing the create.js to create.sj.erb, also I made some small changes to my application.js file. After all that I then added a flash[:note] = you have voted!, then added a function to remove the flash notice after a sec and fadeOut!
For anyone who's interested heres the code:
Application.js
jQuery(document).ready(function() {
$("#vote").bind('click', function(e) {
if (e.target.tagName == "DIV") {
$(this).find(".album_extened").toggle('blind');
}
})
})
create.js.erb
$("#vote").before('<div id="notice"><%= escape_javascript(flash.delete(:notice)) %></div>');
$("#vote_count").html("<%= #album.votes_for - #album.votes_against %>");
$(document).ready(function() {
setTimeout(hideFlashMessages, 1000);
});
function hideFlashMessages() {
$("#vote, #notice").append('').fadeOut(1000);
}
If anyone knows a better why which this can be done please forward!!
A good viewing of [http://railscasts.com/episodes/136-jquery][1]
Reading of [link text][2]
Soon fixed things Thanks Jonathanlink text
[1]: http://railscasts.com/episodes/136-jquery/"Rails Cast ep 136"
[2]: http://www.notgeeklycorrect.com/english/2009/05/18/beginners-guide-to-jquery-ruby-on-rails/"Beginners Guild to jQuery and Rails"
and Thanks Sam for being helpful!!
It seems to me that the current_user in the create method did not get its value set.
How do you set the current_user value? In other plugins, they usually define this as an
instance method or instance variable with accessor.
So maybe changing the create method to the following might help:
def create
#album = Album.find(params[:album_id])
respond_to do |format|
if #current_user.vote(#album, params[:vote])
format.js { render :action => "create", :vote => #vote }
format.html { redirect_to([#album.user, #album]) }
#format.xml { render :xml => #album, :status => :created, :location => #album }
else
format.js { render :action => "error" }
format.html { render :action => "new" }
format.xml { render :xml => #vote.errors, :status => :unprocessable_entity }
end
end
end
You might have missed the # before the current_user.vote

render_to_string stripping markup

I am using render_to_string within a JSON 'render' response. The render_to_string method seems to be striping my HTML, what am I doing wrong here?
Here's a sample:
render :json => {:html => render_to_string(:partial => 'view', :locals => { data => #data} )}
The response is coming through without any markup on it.
Have you tried setting the template format in the respond_to block like this:
format.json do
#template.template_format = :html
#html = render_to_string( :partial => 'view', :locals => { data => #data} )
render :json => { :success => true, :html => #html }
end

Resources