Adding rendered HTML to JSON - ruby-on-rails

Given a controller MapsController:
class MapsController < ApplicationController
def index
#campings = Camping.finm(:all) #in reality a much more complex scope.
respond_to do |format|
format.html
format.json { render :json => #campings }
end
end
end
This renders the JSON just fine. But now, I'd like to pass along some HTML to inject into the DOM:
$.ajax({
dataType: "json",
url: "maps.json?bounding=45.446465,-4.935988,53.944621,17.036668",
}).done(function (data) {
//...
var gInfoWindow = new google.maps.InfoWindow({
content: camping.infowindow
});
//...
$("#campings").append(camping.listing);
});
This JavaScript assumes a .listing and .infowindow attribute in each returned JSON-Object. They should contain HTML,
rendered with the partials campings/_infowindow.html.haml and campings/_listing.html.haml.
Is this the correct angle to tackle this? Or should I rather build the HTML within the JavaScript and avoid sending HTML? If so, is there still a way to use partials to build the actual HTML?
How can I add listing and infowindow to the ObjectsCamping model does not have these fields?

Maybe a bit rough (and not 100% super the "Rails way") but working fine for me in a similar situation:
render :text => {:result => "success",
:document_row => render_to_string(
:file => "admin/documents/_document_row",
:formats => "html",
:layout => false,
:locals => {:documentable => documentable})}.to_json
so roughly just generating a hash and use render_to_string to get the html from th _document_row template.

If you use something like KnockoutJS or another javascript data-binding or templating tool, you can have a skeleton 'template' in the page to start with, that gets filled in with camping listings when you make the ajax request.
The way it works is that you have your table or list or whatever of camping listings bound to an array of camping objects in your Knockout model. When you make your ajax request, you just update that array with the json that comes back. When that array is updated, the DOM is automatically updated to show the new listing. This lets your ajax request get the data only and not all the HTML markup, which means fewer bytes over the wire, and you can separate the act of fetching new data from updating the DOM based on that data.

Related

How does my ajax call know where my json is in rails

I have a javascript file with some ajax in it as follows.
$.ajax({
type: "GET",
contentType: "application/json; charset=utf-8",
url: 'data',
dataType: 'json',
success: function (data) {
draw(data);
},
error: function (result) {
error();
}
});
I also have created a method in a controller which renders json.
class GraphController < ApplicationController
def index
end
def data
render :json => User.select('value').map(&:value)
end
end
So my question is, how does rails know where the json is coming from especially as I'm not returning a physical file from my controller. What happens if I also have a physical .json file in my folder structure? Is there a heirarchy of how a view will look for a json file (eg physical file>jbuilder file>controller action)?
Every Action must render something.
Either you render something explicitly or rails will look for a page with name similar to the action in inside respective controller's folder in views.
You may render an html.erb, .json, .haml etc from views( provided you specify respond to format)
If you are rendering someting explicitly (which is true in your case, as json) Rails wont bother to look into views folder.
Or otherwise you may just skip render :json statement and specify that object in .json file, with respond to :json.
Here in your scenario, you are rendering a json object, which will be accepted in the success: section of the AJAX function's data arguement.
in ajax call.. contentType: "application/json; charset=utf-8", defines what is the type of request you are querying with rails.What that says is, "if the client wants HTML in response to this action, just respond as we would have before, but if the client wants XML, return them the list of people in XML format." (Rails determines the desired response format from the HTTP Accept header submitted by the client.).
Take a look respond_to api how rails responds to different types of request -js/xml/html/json
so you can try this in your controller as well..edit the data action like this and try..any call to data such as js/html/xml/json will work and rails will understand what type of response it needs to send.
def data
format.html { redirect_to(user_list_url) }
format.js
format.xml { render :xml => #users.to_xml(:include => #accounts) }
format.json {render :json => User.select('value').map(&:value) }
end
to render any error from controller to view..can be done like this:-
if #user.present?
format.json {render :json => User.select('value').map(&:value) }
else
format.js { render :json => #user.errors.full_messages.join(' '),
:status => 400 }
end
use this in view in ajax.error function like this
.error(function(data) {
$("#show_error").html("An Error Occurred,Please try again.");
});
HOPE THIS HELPS

Rails Controller -- just return the processed data (dont load into a view)

I'm new to Ruby and Rails. I just completed a course in Laravel, so I am aware of the MVC system(not a newbie as far as the basic concepts are concerned).
I have a rather simple question,
I am sending a POST request to my RAILS REST API,the body of the post request contains a json encoded string like this--->
Array ( [method] => POST [timeout] => 45 [redirection] => 5 [httpversion] => 1.0 [blocking] => 1 [headers] => Array ( ) [body] => {"post_content":"here is the post","post_title":"here we are ","post_author":"1"} [cookies] => Array ( ) )
As you can see,its coming from my php based blog.
My rails API is supposed to be taking the post content and automatically adding links to certains words, by comparing the words with some stuff that i have in an SQLite database.
Ok, so my problem is this:
I just want the response from the Rails controller, I dont want anything loaded into a view. The Rails Controller - returns the content, with 'a href' tags around words that are found in my database. This is to be sent back as the response to my post request, and i want to access it directly as the body of the response.
As of now I dont know how this is to be done. Laravel has the ability to 'return' whatever you want to , at the end of the Controller Action, but in Rails, everything seems to want to load into a view.
I have researched some questions here and found one which said 'render :nothing => true',but that renders nothing at all.Here is what my code looks like.
def process
content = params['post_content']
##perform db function and get back the content with the links embedded.
##HOW TO RETURN THIS CONTENT.
end
Personally, I think, i have to use the render_to_string method, but I have no idea how to do this.
Any help is appreciated.
Best Regards,
Richard Madson.
Some options to consider:
Render just the raw string as the http response body:
render :text => content
Render a view without the default surrounding layout:
render :layout => false
In that case your view could just be:
<%= #content %>
Or render the content as json:
render :json => { :content => content }
The question is, what do you want returned? Text? XML? JSON?
I'm going to assume you want JSON back based on the JSON going in.
respond_to do |format|
format.json { render json: #someobject }
end
It might be helpful to see the rest of the controller method.
If I understand correctly believe what you are looking for is
render :text => "response"
there is also - JSON, XML, nothing, js, file, etc - more information here http://guides.rubyonrails.org/layouts_and_rendering.html

best_in_place - use updated value back in view

I have an idea and a problem I can't seem to find answer or solution to.
Some info if required later or helpful:
Rails version 3.2.9
best_in_place (git://github.com/straydogstudio/best_in_place.git)
Ruby 1.9.3p327
Ok, so i have settings page where i can update individual setting by editing them with use of best_in_place gem. Works fine. Happy with that.
Some of the settings are interconnected, meaning, i have to sum or subtract them.
As a helpful tip for the user, in my view, right beside the in place form for that settings there is also a calculated value.
Now, of course, I would like to see this value be update along with the attribute itself.
I can't find a way to do that.
If i do it with the :data => it works, but i get the old and not the new value, so my view is always "1 step behind".
i have also tried with update.js.erb and _test.html.erb partial, but javascript file doesn't work. It is like it doesn't exist. I have double, triple checked where to put it and it is OK (app/views/controller/_partial.html.erb)
So. Pretty straightforward question would be; how can i access an updated value and use it back in view to update calculations. I personally think I should go with the partial and js file - but I have no clue why JS file isn't picked up. Any idea on that?
If there are any other options, i would more than appreciate the hint.
Thanks!
--EDIT (code added)
view:
<td>
<%= best_in_place #s,:pay_after_bonus, :display_with => :number_to_percentage, :type => :input, :nil => "Klikni tu za spremembo!", :cancel_button=> "Prekliči" %>
Cena: <span id="test"><%= number_to_currency(#s.family_member_price - ((#s.pay_after_bonus * #s.family_member_price)/100)) %></span>
</td>
settings_controller.rb:
def update
#s = Setting.find(params[:id])
respond_to do |format|
#s.update_attributes params[:setting]
#s.create_activity :update, :params => { :setting => params[:setting].keys.first }, owner: current_user
format.json { respond_with_bip(#s) }
format.js
end
end
update.js.erb:
$( "#test" ).html( "<%= escape_javascript( render( :partial => "update") ) %>" );
_update.html.erb:
<strong>Test</strong>
-- EDIT 2:
OK, apparently it is possible to do something like I want this way:
$('.best_in_place[data-attribute="model_attribute"]').bind(
"ajax:success", function(event, data) {
// function that will update whatever
});
in combination with
// respond to json request with
render :json => {"model" => #model}
&
"ajax:success", function(event, data) {
var result = $.parseJSON(data);
// from here the result var will be accessible with all the data returned by the controller.
// result.model is your object - use result.model.attribute to get specific values...
}
But here it ends for me.
I don't know how to use render :json => {"model" => #model} in my case, as it has to be done in combination with format.json { respond_with_bip(#s) }.
Where do I put render in controller?
Currently I get 500 internal server errors trying to do this as a response.
I have found this solution here.
Thanks!!
In the ajax callback you can make another request to get the partial you want:
$('.best_in_place.myclass').bind("ajax:success", function () {
$.getScript("http://www.someurl.com");
});
Then in the action you render a JS file (eg: show.js.erb), where you replace the target element with the results of the render:
$("#div-<%= #div.id %>").replaceWith("<%= escape_javascript(render(partial: 'some/partial', :layout => false)) %>");
You can use jQuery to parse the dom for the element that best in place just changed, and get the updated value from there. For example, of you have this code (haml)
= best_in_place #user, :name, :classes => 'name-edit'
Then your callback would look like this (coffeescript)
$('.name-edit').on 'ajax:success', (event, data, status, xhr) ->
newValue = $('.name-edit').html # could also use .attr() here
$('.some-other-widget').html(newValue) # again could also set .attr here
You can even skip looking up the new value with jQuery. In the context of the callback handler, 'this' represents the element the call was made from, so you could just do
$('.name-edit').on 'ajax:success', (event, data, status, xhr) ->
$('.some-other-widget').html this.innerHTML
and get the new value to the other widget that way. My guess is the event returned by the ajax handler also has currentTarget, which again would be the widget that trigged the ajax request. My only worry on all this would be that your success handler somehow beats the best in place handler, and you get the widget before it's updated. In my testing that hasn't ever happened.
I just answered a question like that:
Answer here
but instead of just inserting the value you need to use the sum that you need.

Where to store view parameters in an AJAX session?

In a non-AJAX web app, the URL would contain my view parameters (e.g. mysite?page=2&sort=name). In an AJAX app, where do I store the same info? In the Session object?
I'm assuming you want to know how to pass additional params with an AJAX call. This really depends on how you're formulating the AJAX call.
If you're using the built-in Rails helpers, you can pass additional params inside the url_for helper. For example, lets say that you have a products route and you want to AJAX load a list of all products. The link_to helper might look something like this (Rails 3.2)
link_to "All Products", products_path(:page => 2, :sort => "name"), :remote => true
If on the other hand you're using a JavaScript framework like jQuery, you can pass additional params using the data option. For example
$.ajax({
url: "/products",
data: {
page: 2,
sort: "name"
},
success: function(data) {
// handle success
},
failure: function(data) {
// handle failure
}
});
Storing this data (page, sort, etc.) can be done multiple ways also. The easiest way would be to store this data inside a JavaScript variable.
window.page = 2;
window.sort = "name";
Another solution is to store this information in the data attribute of a particular DOM element on the page. For example, if you have a <div id='products'> that contains a list of the paginated, sorted products, you could store the information like this (jQuery)
$("#products").data("page", 2);
$("#products").data("sort", "name");
Generally speaking, you don't structure you're requests differently for AJAX in Rails. You'll just add the :remote => true attribute to your link or form, then make the controller action respond_to js
respond_to do |format|
format.js
end
And then put your_action.js.erb in your views and write javascript that updates the dom in the appropriate way.

Rails Rendering a partial within JSON

I am trying to render a partial inside a JSON file so that I can use it via AJAX. Currently in my JSON file I have:
<% self.formats = ["html"]%>
{
"html": "<%= raw escape_javascript(render(:partial => 'shared/mini_posts', :locals => {:type => "left"}).to_json )%>"
}
This currently returns no response, but my logs show that shared/mini_posts was rendered.
Note that if I try something like:
{
"html" : "test"
}
This returns correctly.
My jQuery looks like:
$j.ajax({
url('/thepage.json'),
dataType: 'json',
success: function(data){
console.log(data);
}
})
In my case, I had the same problem for about a day and a half and after trying lots of combinations of escape_javascript, to_json, render ... content_type, etc I finally achieved what I was looking for, that is rendering a HTML partial in a json response.
So in your controller you have an action like
def index
#candidatos = Candidatos::Base.paginate(page: params[:page], per_page: 3).to_a
respond_to do |format|
format.html # index.html.erb
format.json # index.json.erb
end
end
and if the request had a .json it will use the index.json.erb template, and in my case that template is something like
<% self.formats = ["html"] %>
{
"html":<%= thumbnails_tag(#candidatos).to_json.html_safe %>
}
Note the self.formats = ["html"] is necessary because otherwise the "view" won't find the partial because it will look for a .json partial. and more important, don't use escape_javascript because it will fill the html with \t and \n. In other words, the idea is to pass the output of your partial to .to_json and then to .html_safe.
thumbnails_tag is just a helper I created because I'm using the partial in lots of parts of the app, but basically it has something like
def thumbnails_tag objs
#Uncomment the line below to test when no much data available
# #listas.fill(#listas.first, 0..6)
thumb_span = 4
case #candidatos.length
when 1..3
thumb_span = 12 / #candidatos.length
else
thumb_span = 4
end
thumbs = {span: thumb_span}
render partial: 'candidatos/thumbnails', locals: {candidatos: #candidatos, thumbnail_options: thumbs }
end
Finally, and just as an example, with this approach, in your .js assets you can do something like:
$.get('http://localhost:3000/candidatos.json?page=2', function(d){}, 'json')
.success(function(d){
$('#presidentes div.row-fluid .thumbnails').parent().append(d.html);
})
.error(function(event,error){
console.log(error);
})
No need to gsub for \t and \n in your rails view or JSON.parse string in your Javascript.
You need to change your controller. In the respond_to part you need to add json rendering. Like this:
respond_to do |format|
format.json { render :json => #instancevar }
....
...
..
end
Then you can simply add .json to your url and you will receive the data formated as json. What you might need to do is disabeling the JSON root hich is automaticly added by default. Just add this line to your environment (development.rb, production.rb,...) configuration:
config.active_record.include_root_in_json = false
This is important when you are parsing the json.
You can't call to_json on a partial... it's a method of ActiveRecord. If you want json there, then it should be inside the partial.

Resources