Read cross domain JSON response - ruby-on-rails

<script>
$.ajaxSetup( {contentType: 'application/json'} );
function submit_data(f){
alert('submitting')
var data_string = $(f).serialize();
$.ajax({
url: "http://localhost:3000/application/1/contact_us.json?jsonpcallback=?"+data_string,
dataType: "jsonp",
type : 'post',
processData: false,
crossDomain: true,
contentType: "application/json",
jsonp: false,
jsonpcallback: result()
});
}
function result(){
alert('back in')
alert(data)
}
function jsonp1300279694167(){
alert('dhoom')
}
</script>
I have script above querying across domain and posting data within a form.
Everything seems to work fine. JSON response can be seen in the firebug console. I want to process the response and display status messages accordingly to the user. How should I achieve it?
UPDATE
I have tried as suggested by T.J. Crowder but have no luck yet. The modified code is as below
function submit_data(f){
alert('submitting')
var data_string = $(f).serialize();
$.ajax({
url: "http://localhost:3000/application/1/contact_us.json?"+data_string,
dataType: "jsonp",
crossDomain: true,
success: handleSuccess()
});
}
function handleSuccess(data) {
alert("Call completed successfully");
alert(data);
}
This does not accesses data and alerts undefined. If I try to pass it from success: handleSuccess() it errors and redirects with a http request.
I am getting response from a Ruby on Rails application. Here is the method I am hitting
def create
errors = ContactUsForm.validate_fields(params)
logger.info errors.inspect
if errors.blank?
respond_to do |format|
format.json {render :json => {:status => 'success'}.to_json}
end
else
respond_to do |format|
format.json {render :json => {:status => 'failure', :errors => errors}.to_json}
end
end
end
Is there any thing that I need to configure in my rails app

You're close. You just use the success callback as usual (see the ajax docs), not a special one:
$.ajax({
url: "http://localhost:3000/application/1/contact_us.json?jsonpcallback=?"+data_string,
dataType: "jsonp",
type : 'post',
processData: false,
crossDomain: true,
contentType: "application/json",
jsonp: false,
success: function(data) {
// Use data here
}
});
Also, your code:
jsonpresponse: result()
...would call the result function and then use its return value for the jsonpresponse property of the ajax call. If you want to use a separate function, that's fine, but you don't include the (), so:
$.ajax({
url: "http://localhost:3000/application/1/contact_us.json?jsonpcallback=?"+data_string,
dataType: "jsonp",
type : 'post',
processData: false,
crossDomain: true,
contentType: "application/json",
jsonp: false,
success: result
});
function result(data) {
// use `data` here
}
Also, I'm pretty sure you don't need/want the jsonp parameter if you use success, so:
$.ajax({
url: "http://localhost:3000/application/1/contact_us.json?jsonpcallback=?"+data_string,
dataType: "jsonp",
type : 'post',
processData: false,
crossDomain: true,
contentType: "application/json",
success: result
});
function result(data) {
// use `data` here
}
Finally: Are you sure you want to set contentType? That relates to the content being sent to the server, not the content being received from it. If you're really posting JSON-encoded data to the server, great, you're fine; but it looks like you're using jQuery's serialize function, which will not produce JSON (it produces a URL-encoded data string). So you probably want to remove contentType as well, both from the call and from the ajaxSetup call.

I hope if you can try jQuery-JSONP
jQuery-JSONP How To
[Example]
$.getJSON('server-url/Handler.ashx/?Callback=DocumentReadStatus',
{
userID: vuserID,
documentID: vdocumentID
},
function(result) {
if (result.readStatus == '1') {
alert("ACCEPTED");
}
else if (result.readStatus == '0') {
alert("NOT ACCEPTED");
}
else {
alert(result.readStatus);
}
});

I tried many tutorials including the answers above but had no luck. So I implemented it something like below
Form
<form action="" onsubmit="submit_data(this, '1'); return false;">
// some form fields
</form>
Submit function for form
<script>
function submit_data(f, app_id){
var data_string = $(f).serialize();
$.ajax({
url: "http://www.example.com/"+app_id+"/contact_us.js?"+data_string,
dataType: "jsonp",
crossDomain: true,
});
}
function show_errors(jsonOb)
{
$("span.error").remove();
$.each(jsonOb, function(key,val){
$("#contact_us_form_"+key).after("<span class=error>"+val+"</span>")
});
}
</script>
In my controller
def create
#application = Application.find params[:application_code]
#errors = ContactUsForm.validate_fields(params, #application)
#application.save_contact_us_form(params[:contact_us_form]) if #errors.blank?
respond_to do |format|
format.js #{render :json => {:status => 'success'}.to_json}
end
end
And finally in create.js.erb
<% if #errors.blank? %>
window.location = "<%= #application.redirect_url %>"
<% else %>
var errors = replaceAll('<%= escape_javascript(#errors.to_json)%>', """, "'")
var errors_json = eval('(' + errors + ')')
show_errors(errors_json);
function replaceAll(txt, replace, with_this) {
return txt.replace(new RegExp(replace, 'g'),with_this);
}
<% end %>
This way I called submit_form on form submit and called show_errors javascript function from server it self. And it works..
But still I would like to have comments if this is a worst solution?

Related

Passing Json response to view in Rails Ajax Datatable

I have an index method that respond with Json call to Datatable such as:
respond_to do |format|
format.html
format.json { render json: PeopleDatatable.new(params, user: current_user, view_context: view_context) }
end
I would like to be able to pass an array of all the IDs in the response to a dom in my view such as <div id: "people">1,2,3,4</div>
As per the gem description, the People records are generated in the
app/datatables/people_datatable.rb
using:
def get_raw_records
User.all
end
I tried adding the following in the view's script:
$(document).ready(function () {
$.ajax({
type: "GET",
url: "<%= peoples_path(format: :json) %>",
dataType: "json",
success: function(data) {
alert(data.name)
$('#bouba').html(data);
}
});
});
but the result is an undefined object class.
What would be the easiest way to do so please?
I am using the following gem for my datatable Rails ajax Datatable
Open /people.json and see what you get as a response, it looks something like this:
{
"recordsTotal": 2,
"recordsFiltered": 2,
"data": [
{
"id": "1",
"name": ""
},
{
"id": "2",
"name": ""
},
]
}
Now that you know what the structure looks like, send ajax request to that url:
<div id="people-ids"></div>
<script type="text/javascript">
$(document).ready(function () {
$.ajax({
type: "GET",
// send request to the correct url: "/people.json"
url: "<%= people_path(format: :json) %>",
dataType: "json",
success: function({data}) {
// ^
// extract "data" attribute from the response
console.log(data) // you can see what you get in the console
// extract ids
const user_ids = data.map(user => user.id)
// do what you like with the ids
$("#people-ids").html(user_ids.join());
}
});
});
</script>

Sending data from view to controller AJAX

how can I send the var lang to the controller so I can use it in partiel. here is my shot:
$("#search-select").on("click", function() {
var lang = $('#search-select').dropdown('get value');
$.get({
url: translations_url
data: lang,
success: function(){
console.log('data sent');
}
});
});
EDIT
current code:
$("#search-select").dropdown();
$("#search-select").on("click", function() {
var lang = $('#search-select').dropdown('get value');
$.get({
url: "#{translations_url}",
dataType: "script",
data: {
lang: lang
}
});
});
problem: params[:lang] still don't work in controller
Set correct _path to your post method:
$.ajax({
url: '<%= controller_path %>', method: 'POST',
beforeSend: function(xhr) {xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'))},
data: { lang: lang },
dataType: 'json',
success: function (data) {
console.log(data);
}
});
Now you can work with lang in your controller
def method
params[:lang] # do something
answer = 'Then, you can return some data to view'
respond_to do |format|
format.json { render json: answer }
end
end
you're missing , after url: translations_url, also if you can send data as JSON with key and value, like data: {lang: 'value'}, also you don't need to specify method name if you're using GET, see the below example
$.ajax({
url: translations_url,
data: {lang: 'value'},
success: function(){
console.log('data sent');
}
});
if you need to use POST Method then include method: 'post' incase jquery ajax method doesn't call js.erb file you need to add dataType: 'script'
You can't use route path helpers on the frontend. But you can send proper URL from backend to frontend via data-attribute:
#search-select{ data: { path: translations_url } }
And then in your js:
$("#search-select").on("click", function() {
var url = $(this).data('path'),
data = { lang: $(this).dropdown('get value') };
$.get({
url: url,
data: data,
success: function(){
console.log('data sent');
}
});
});

Ruby Devise sign up with AJAX not getting json response?

I have followed this tutorial: https://blog.andrewray.me/how-to-set-up-devise-ajax-authentication-with-rails-4-0/ And am using rails 5.1.
I have implemented the json response in the controller:
class RegistrationsController < Devise::RegistrationsController
respond_to :json
end
And when I call the ajax I only get an Html/Text response:
function createUser(callback) {
$.ajax({
type: "POST",
url: window.urls.createUser,
data: {
authenticity_token: $("meta[name=csrf-token]").attr("content"),
user: grabOrderFormUserData()
},
success: function(data) {
console.log("Data: " + data);
},
error: function (data) {
//console.log("error");
}
})
}
That call works fine, but returns the HTML page of the sign up.
The url I use is createUser: hostUrl + '/users/'
What did I miss?
And no, if I add .json to my url, it will respond with 500 error code.
I think you missed to mention dataType: "json" with your ajax call , try this
function createUser(callback) {
$.ajax({
url: window.urls.createUser,
type: "POST",
data: {`enter code here`
authenticity_token: $("meta[name=csrf-token]").attr("content"),
user: grabOrderFormUserData()
},
dataType: "json",
success: function(data) {
console.log("Data: " + data);
},
error: function (data) {
//console.log("error");
}
})
}
and also in your controller try to call this block in case if you are not getting json response,
respond_to do |format|
format.json {
render json: {.....}
}
end
thank you.

Best way to return a string from a controller to ajax call

I want to create an action that returns me a single string value:
def delay_calulation()
dr = Dr.find(params[:id])
delay = dr.calc()
respond_to do |format|
format.json { render json: {"value" => delay}}
end
end
but I a "fail" in my ajax call:
$("#btn_delay").on("click", function () {
$.ajax({
type: "GET",
dataType: "script",
url: "/drs/delay_calulation/1"
})
.done(function(response){
console.log(response);
})
.fail(function(response){
console.log(response);
});
});
How can I get a single string, or something like that.
You need to pass id to the controller action while calling through Ajax. You can retrive the string by using the key name that you have mentioned in the controller.
$.ajax({
url: '/drs/delay_calulation',
data: {id: (you need to pass the id)},
type: "get",
dataType: "json",
success: function(data){
var a = data["delay"]
},
failure: function(data){
var a = data["delay"]
}
});

values are not saved in session array

In my controller action i initialize a session of array and inserting values. These values are coming from the client side through ajax, so the page is not refreshed while inserting these values to an array.But suprisingly every time it iniatialize a new session instead of inserting to the same defined session. Here is my code
controller
def receive_tags
parser = Yajl::Parser.new
#hash = parser.parse(request.body.read)
log=Logger.new(STDOUT)
log.error(#hash)
session[:tags]||=[]
session[:tags] << #hash["tag"]
unless session[:tags].empty?
log.error(session[:tags] ) #this keeps printing the current value i was expecting it to print a list of values including the previous
end
render :nothing=>true
end
Ajax
var myobj={tag:"mytag"};
$.ajax({
url: 'ips/receive_tags',
type: 'post',
contentType: 'application/json; charset=UTF-8',
accept: 'application/json',
dataType: 'json',
data:JSON.stringify(myobj),
success: function(res) {
if (res.ImportResponse !== void 0) {
console.log('Success: ' + res);
} else if (res.Fault !== void 0) {
console.log('Fault: ' + res);
}
},
error: function() {
console.error('error!!!!');
}
});
This sounds like the browser isn't saving cookies, which would explain the behavior you are seeing where the session is reinitialized every time. To confirm this, you can do
print "Session ID: #{request.session_options[:id]}"
in your action and see if the session id changes for each request. If it does, check your browser privacy settings and see if it is saving any cookies.
Finally i figured it out, The problem is i wasn't setting the request header for the token before sending ajax call so Rails was receiving data without the token, thus kept assuming it is a new object for every request.You can read more here.To set the request header add
beforeSend: function(xhr) {
xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'));
}
Below is my ajax function that works
var myobj={tag:"mytag"};
$.ajax({
url: 'ips/receive_tags',
type: 'post',
contentType: 'application/json; charset=UTF-8',
accept: 'application/json',
dataType: 'json',
data:JSON.stringify(myobj),
beforeSend: function(xhr) {
xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'));
}
success: function(res) {
if (res.ImportResponse !== void 0) {
console.log('Success: ' + res);
} else if (res.Fault !== void 0) {
console.log('Fault: ' + res);
}
},
error: function() {
console.error('error!!!!');
}
});

Resources