I've been trying for quite some time now to figure out why the JSON object I'm passing through AJAX to Rails with Typhoeus isn't working properly. Apologies if this is a newb question but I'm relatively new to web dev.
I've spent all day looking at docs, googling, and on SO but I haven't been able to figure out much for some reason.
I'm trying to pass a request to Google's QPX Express API for flight search and the docs say to send a JSON obj in the following format:
{
"request": {
"passengers": {
"kind": "qpxexpress#passengerCounts",
"adultCount": 1,
"childCount": 0,
"infantInLapCount": 0,
"infantInSeatCount": 0,
"seniorCount": 0
},
"slice": [
{
"kind": "qpxexpress#sliceInput",
"origin": "SFO",
"destination": "HNL",
"date": "2015-04-03",
"maxStops": 0,
"maxConnectionDuration": 0,
"preferredCabin": "COACH",
"permittedDepartureTime": {
"kind": "qpxexpress#timeOfDayRange",
"earliestTime": "00:00",
"latestTime": "11:59"
},
"permittedCarrier": [
"VX",
"UA"
],
"alliance": "",
"prohibitedCarrier": [
""
]
}
],
"maxPrice": "USD1000.00",
"saleCountry": "US",
"refundable": false,
"solutions": 1
}
}
I have this stored a variable which is referenced in the AJAX request below as 'reqBody':
$.ajax({
url: '/search',
dataType: 'json',
contentType: 'application/json',
method: 'POST',
// contentType: "application/json; charset=utf-8",
data: JSON.stringify(reqBody),
success: function(data) {
console.log(data);
}
});
And this is call goes to the rails controller shown here, using Typhoeus to process the request/response:
reqBody = params[:request]
flightRequest = Typhoeus::Request.new(
"https://www.googleapis.com/qpxExpress/v1/trips/search?key=APIKEY",
method: :post,
headers: {'Content-Type'=> "application/json; charset=utf-8"},
body: reqBody,
)
flightRequest.run
#results = JSON.parse(flightRequest.response.body)
respond_to do |format|
format.html
format.json { render json: {
:results => #results
}
}
end
This ends up being the response I get back:
{"results":{"error":{"errors":[{"domain":"global","reason":"parseError","message":"Parse Error"}],"code":400,"message":"Parse Error"}}}
And this is what I get when I look at the obj in pry:
=> {"passengers"=>
{"kind"=>"qpxexpress#passengerCounts",
"adultCount"=>1,
"childCount"=>0,
"infantInLapCount"=>0,
"infantInSeatCount"=>0,
"seniorCount"=>0},
"slice"=>
[{"kind"=>"qpxexpress#sliceInput",
"origin"=>"SFO",
"destination"=>"HNL",
"date"=>"2015-04-03",
"maxStops"=>0,
"maxConnectionDuration"=>0,
"preferredCabin"=>"COACH",
"permittedDepartureTime"=>
{"kind"=>"qpxexpress#timeOfDayRange", "earliestTime"=>"00:00", "latestTime"=>"11:59"},
"permittedCarrier"=>["VX", "UA"],
"alliance"=>"",
"prohibitedCarrier"=>[""]}],
"maxPrice"=>"USD1000.00",
"saleCountry"=>"US",
"refundable"=>false,
"solutions"=>1}
What's going on here? Shouldn't the object be a string since I stringified it in the AJAX request? Is this why there's a parsing error when I send the object to the QPX Express API?
Any help is highly appreciated!
Thanks!
Just a thought,
did you require 'json' in your controller?
The other thing you could try is the variant of parse
parse! which can be used for safe safe sources.
here is a link!
How do I parse JSON with Ruby on Rails?
good luck
Related
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>
I am trying to implement a tampermonkey script that triggers an API call to a Jira instance to create a ticket with some information found in the page I am on (on a different domain).
Here's what I've tried:
async function createJiraTicket() {
let elements = await obtainThingsForCreatingJiraTicket();
let createJiraTicketUrl = `https://${jiraDomain}/rest/api/latest/issue`;
let requestDataForCreation =`
{
"fields": {
"project": { "key": "${elements.project}" },
"summary": "${elements.title}",
"description": "nothing",
"issuetype": {"name": "Issue" }
}
}`;
GM_xmlhttpRequest ( {
method: "POST",
url: `${http}://${createJiraTicketUrl}`,
user: 'user:pwd', // also tried user:'user', password:'pwd',
data: requestDataForCreation,
header: 'Accept: application/json',
dataType: 'json',
contentType: 'application/json',
onload: function (response) {
jiraTicketLog(`[Ajax] Response from Ajax call Received: `);
}
} );
However, when I run createJiraTicket(), I am getting the following error:
Uncaught TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them
at <anonymous>:1:7
I have established the correct #connect tags on the script, so I am pretty blind on where the problem may be...
Can someone help?
Thanks
So I came up with the answer to fix it, apparently it was a number of different details:
So,
Authorization had to be included onto the headers, coded on base64 and keyworded "Basic".
User-Agent needs to be overriden on headers, with any dummy string.
overrideMimeType needed to be set to json.
That all made the trick.
This was the working code.
let createJiraTicketUrl = `//${jiraDomain}/rest/api/latest/issue`;
let authentication = btoa('admin:foobar1');
GM.xmlHttpRequest({
method: "POST",
headers: {
'Accept': 'application/json',
"Content-Type": "application/json",
"Authorization": `Basic ${authentication}`,
"User-Agent": "lolol"
},
url: `${http}:${createJiraTicketUrl}`,
data: JSON.stringify(requestDataForCreation),
dataType: 'json',
contentType: 'application/json',
overrideMimeType: 'application/json',
onload: function (response) {
let url = `${http}://${jiraDomain}/browse/${JSON.parse(response.response).key}`;
log(`${JSON.parse(response.response).key} ticket created: ${url}`);
openJiraTicket(url);
}
UPDATE I've also updated the mapping to include pin as the examples seem to suggest. Also, here's an temporary instance with some data to work with: https://21991e47cdc7caa8000.qbox.io/profiles/lead/_search
I've followed the instructions by ElasticSearch. Using this request:
$.ajax({
url: 'https://21991e47cdc7caa8000.qbox.io/profiles/lead/_search',
method: 'GET',
data: {
sort: [{
_geo_distance: {
"pin.location": [49.8998, -97.1375],
order: "asc",
unit: "km"
}
}]
},
success: function(response) {
console.log(response);
}
});
Does not return with calcuated distance or sorted by distance. I've also tried using "location".
Here's my mapping: https://21991e47cdc7caa8000.qbox.io/profiles/lead/_mapping
Any ideas?
I've managed to get it working, Please see the difference,
I converted data as json before quering, and added some configuration( changed dataType to json, and request type to POST, as we know GET request generally don't have body, only POST request does.
var request = {
sort: [{
_geo_distance: {
"pin.location": [
49.8998, -97.1375],
order: "asc",
unit: "km"
}
}]
};
$.ajax({
url: 'https://21991e47cdc7caa8000.qbox.io/profiles/lead/_search',
type: 'POST',
crossDomain: true,
dataType: 'json',
data: JSON.stringify(request),
success: function (response) {
console.log(JSON.stringify(response));
}
});
Hope this helps.
I've tested, and it should work for you too.
The example given uses pin.location, not location or lead.location.
Additionally, pin.location is an array of length 2, not an object with two fields as you are using it. This seems pretty counter-intuitive to me, as the location field in most other api calls is an object like you are using.
Try this:
$.ajax({
url: "https://myhostedes.com/profiles/lead/_search",
method: "GET",
data: {
"sort": [{
"_geo_distance": {
"pin.location": [49.8998, -97.1375],
"order": "asc",
"unit": "km"
}
}]
},
success: function(response) {
console.log(response);
}
});
Note: I don't have access to an elastisearch instance at the moment, so I haven't been able to run this yet.
I'm using Ruby on Rails, and I have a button that can create a post through AJAX, using this:
$.ajax({
beforeSend: function(xhr) {
xhr.setRequestHeader(
'X-CSRF-Token',
$('meta[name="csrf-token"]').attr('content'))},
url: "/posts/",
type: "POST",
data: {
post: {
title: "Cheese",
content: "Cake",
}
}
});
How do I format the data to create multiple posts at once, for example
posts = [
{
title: "Cheese",
content: "Cake"
},
{
title: "Key Lime",
content: "Pie"
}
]
so I can insert multiple objects with one POST?
I have a list of titles and contents. Might I have to construct a JSON object out of these?
Regardless of whether this is good Rails practice, how do I do this? Also, where might I look for how to format such HTTP requests?
Your jQuery call won't change much:
$.ajax({
beforeSend: function(xhr) {
xhr.setRequestHeader(
'X-CSRF-Token',
$('meta[name="csrf-token"]').attr('content'))},
url: "/posts/",
type: "POST",
contentType: "application/json",
data: JSON.stringify({
posts: [
{
title: "Cheese",
content: "Cake",
},
{
title: "Key Lime",
content: "Pie"
}
]
})
});
In your Rails action, you will be able to access your posts as an array of hashes via params[:posts].
class ThingsController < ApplicationController
def batch_create
params[:posts].each do |post|
Post.create post
end
end
end
Explanation
Using JSON.stringify causes your data to be serialized as JSON. Set contentType to application/json to add the "Content-Type: 'application/json'" header to your POST. That will clue Rails to interpret your POST as JSON.
$.ajax({
url: "/rooms.json",
dataType: "json",
data: {
q: req.term
},
success: function (data) {
alert('test');
responseFn($.map(data.room, function (item) {
alert('test1')
return {
label: item.title
value: item.title
}
}));
}
});
data from /rooms.json?q=a looks like below:
[{
"room": {
"created_at": "2011-05-19T18:08:04Z",
"title": "Great Office Space for Rent!",
"cost": 450,
"updated_at": "2011-05-19T18:08:04Z",
"property_id": 4,
"maximum_capacity": 234,
"id": 15,
"fulladdress": "550 12th St NW, Washington D.C., DC 20005, USA",
"user_id": null,
"phone": "301-395-7578",
"description": "Great office space to rent in DC\r\n\r\nPlease contact. ",
"email": "something#gmail.com"
}
}]
In the above code, I see the first alert but not the second alert so something is going wrong in the handling of the data from the json request.
What should I do to fix this?
Update
After playing around w/ some code I figured it out.
I had to tweak the rails controller to render json as below
format.json {render :json => #events.map(&:attributes)}
Furthermore, for jQuery code I had to remove .room from the code below
responseFn($.map(data.room, function (item) {
silly me
in rails code:
format.json {render :json => #days.map(&:attributes)}
in jQuery code
responseFn( $.map( data, function( item ) {