Record saves, promise rejects with custom REST adapter - rest

I'm writing an ember-data adapter for the DreamFactory services platform and am running into an issue I think is related to my adapter.
When updating an existing record the promise resulting from model.save() is ALWAYS rejected with an error of
Assertion Failed: An adapter cannot assign a new id to a record that already has an id. <App.Event311:1> had id: 1 and you tried to update it with null. This likely happened because your server returned data in response to a find or update that had a different id than the one you sent
Thing is - the request to the REST API and the response back from the REST API have the same ID!
Request (PUT)
{
"record": {
"id": "1",
"title": "Sample Event",
"date": "7/20/2013",
"type": "success",
"desc": "My first sample event."
}
}
Response
{
"record": [
{
"id": 1,
"title": "Sample Event",
"date": "7/20/2013",
"type": "success",
"desc": "My first sample event."
}
]
}
The really weird thing is the record still updates properly both in the store AND in the database!
I have a working JSBin at http://emberjs.jsbin.com/mosek/1/edit that illustrates the problem. My custom adapter is on GitHub at https://github.com/ultimatemonty/ember-data-dreamfactory-adapter. The JSBin as well as my app are using Ember 1.7.0 and ED 1.0.0-beta.9
EDIT
The JSBin is attached to my personal hosted instance of DreamFactory - I haven't done anything with it outside of allowing access from JSBin but please be gentle :)
* EDIT #2 *
The updateRecord code is accessible on GitHub at https://github.com/ultimatemonty/ember-data-dreamfactory-adapter/blob/master/lib/ember-data-dreamfactory-adapter.js#L106 but here is the full method for reference:
updateRecord: function(store, type, record) {
var data = {};
var serializer = store.serializerFor(type.typeKey);
serializer.serializeIntoHash(data, type, record);
var adapter = this;
return new Ember.RSVP.Promise(function(resolve, reject) {
// hack to make DSP send back the full object
adapter.ajax(adapter.buildURL(type.typeKey) + '?fields=*', "PUT", { data: data }).then(function(json){
// if the request is a success we'll return the same data we passed in
resolve(json);
}, function(reason){
reject(reason.responseJSON);
});
});
}

The adapter/serializer you're using is expecting you to return a response without the type in it:
{
"id": 1,
"title": "Sample Event",
"date": "7/20/2013",
"type": "success",
"desc": "My first sample event."
}
Example: http://emberjs.jsbin.com/tigiza/1/edit
You can see it here in the extractSingle, where it tries to wrap the payload in in another object with the type specified
EmberDreamFactoryAdapter.Serializer = DS.RESTSerializer.extend({
extractArray: function(store, primaryType, payload) {
var namespacedPayload = {};
namespacedPayload[Ember.String.pluralize(primaryType.typeKey)] = payload.record;
return this._super(store, primaryType, namespacedPayload);
},
extractSingle: function (store, primaryType, payload, recordId) {
var namespacedPayload = {};
namespacedPayload[primaryType.typeKey] = payload;
return this._super(store, primaryType, namespacedPayload, recordId);
},
Your response looks like this:
{
"record": [
{
"id": 1,
"title": "Sample Event",
"date": "7/20/2013",
"type": "success",
"desc": "My first sample event."
}
]
}
Then the serializer kicks in, and it looks like this:
{
event:{
"record": [
{
"id": 1,
"title": "Sample Event",
"date": "7/20/2013",
"type": "success",
"desc": "My first sample event."
}
]
}
}
When really, the serializer should have it looking like this:
{
event:{
"id": 1,
"title": "Sample Event",
"date": "7/20/2013",
"type": "success",
"desc": "My first sample event."
}
}
You can see from the second example, the serializer wraps it in the type, then Ember Data says, hey, give me the id, so it looks at event.id which is undefined, because it lives under event.record[0].id

Related

The custom payload for the facebook messenger integration only shows up the first time it's called and not thereafter

I built a winebot that can suggest food pairings or make recommendations.
The integration with FB Messenger works fine, and it's supposed to call a carousel after a search to show you the various options. I found that when I call on it multiple times it will only display the carousel the first time and not a new one each time.
This is the function that calls the carousel
// CREATE RICH MESSAGES FOR FACEBOOK
function create_carousel(agent, carousel_params) {
agent.context.set({
name: 'carousel_output',
lifespan: 2,
parameters: carousel_params,
});
agent.setFollowupEvent('createCarousel');
agent.add(''); //add a dummy payload
return;
}
IntentMap is set up like this:
// Run the proper function handler based on the matched Dialogflow intent name
let intentMap = new Map();
intentMap.set('createCarousel', create_carousel);
agent.handleRequest(intentMap);
The createCarousel intent is set up with an event createCarousel and an output context called carousel_output
Under the messenger tab it has a text message followed by a payload. The text message and payload both use the content of carousel_output to make a recommendation.
{
"facebook": {
"attachment": {
"type": "template",
"payload": {
"elements": [
{
"image_url": "#carousel_output.product1.image",
"default_action": {
"url": "https://google.com",
"webview_height_ratio": "tall",
"type": "web_url"
},
"subtitle": "#carousel_output.product1.subtitle",
"title": "#carousel_output.product1.title",
"buttons": [
{
"url": "https://www.winemag.com/buying-guide/brovia-2013-garblet-sue-barolo/",
"title": "#carousel_output.product1.price",
"type": "web_url"
},
{
"title": "Some Text",
"payload": "Some Text",
"type": "postback"
}
]
},
{
"image_url": "#carousel_output.product2.image",
"subtitle": "#carousel_output.product2.subtitle",
"default_action": {
"type": "web_url",
"webview_height_ratio": "tall",
"url": "https://google.com"
},
"title": "#carousel_output.product2.title",
"buttons": [
{
"type": "web_url",
"url": "https://www.wine-searcher.com/find/limerick+lane+cellars+rocky+knoll+zinfandel+russian+river+valley+sonoma+county+north+coast/2013",
"title": "#carousel_output.product2.price"
},
{
"title": "Some Text",
"payload": "Some Text",
"type": "postback"
}
]
},
{
"default_action": {
"webview_height_ratio": "tall",
"type": "web_url",
"url": "https://google.com"
},
"image_url": "#carousel_output.product3.image",
"buttons": [
{
"title": "#carousel_output.product3.price",
"type": "web_url",
"url": "https://www.wine-searcher.com/find/charles+smith+k+vintner+the+hidden+sra+wahluke+slope+washington+usa/2009"
},
{
"title": "Some Text",
"type": "postback",
"payload": "Some Text"
}
],
"title": "#carousel_output.product3.title",
"subtitle": "#carousel_output.product3.subtitle"
}
],
"template_type": "generic"
}
}
}
}
What I noticed is that when I call the intent a second or third time , the message appears but the payload does not.
I 've already tried clearing output_context and deleting it but this does not seem to affect anything. I looked through the documentation of how payloads work but nothing specifically referencing the issue.
I was wondering if this may be a limitation on facebook messenger but don't see anything in the logs that is a flag. The function runs and the context is updated each time with the right content but just doesn't display in the bot.
The logs didn't show any errors, but the problem appeared in the data provided to the payload.
The code that creates the payload pulls images 3 at a time from a list of urls. There were only 5 urls provided in the list so on the second run it killed the carousel and did not show an undefined error message or a missing data error. Works fine after adding more urls to the list.

How to create a jsonpath to instagram business account in a batch request with the Graph API?

My goal is to create a batch request with dependent calls as documented here:
https://developers.facebook.com/docs/graph-api/making-multiple-requests#operations
You can reference the results of a previous operation using JSONPath in form post parameters in addition to query string parameters.
I can't get the right JSONPath to make it work when there are multiple elements in the data array that have an instagram_business_account.id (iba_id)
The two calls that I want to make are
/me/accounts?fields=instagram_business_account
/17841400714813297?fields=business_discovery.username(thomasguntenaar){media_count}
my batch looks like
[
{"method":"GET","name":"get-ig", "relative_url":"me/accounts?fields=instagram_business_account"},
{"method":"GET", "relative_url":"{result=get-ig:$.data..instagram_business_account.id}?fields=business_discovery.username(thomasguntenaar){media_count}}"}
]
in the second query you are supposed to put the JSONPath to the instagram business account id
after result=
I get this error back
{
"code": 404,
"body": "{
\"error\": {
\"message\": \"(#803) Some of the aliases you requested do not exist: 17841400714813297,17841403388404550,17841401383243593\",
\"type\": \"OAuthException\",
\"code\": 803,
\"fbtrace_id\": \"FV8qA+oA7fp\"
}
}"
}
Facebooks json response after the first call is
{
"data": [
{
"id": "466912700123917"
},
{
"id": "502655553273897"
},
{
"instagram_business_account": {
"id": "17841400714813297"
},
"id": "503124266815195"
},
{
"instagram_business_account": {
"id": "17841403388404550"
},
"id": "510613645695833"
},
{
"instagram_business_account": {
"id": "17841401383243593"
},
"id": "2061834074114937"
}
],
"paging": {
"cursors": {
"before": "NDY2OTEyNzAwMTIzOTE3",
"after": "MjA2MTgzNDA3NDExNDkzNwZDZD"
}
}
}
When you query the second request like this
?ids=17841400714813297,17841403388404550,17841401383243593&fields=business_discovery.username(thomasguntenaar){username,media_count}
the response looks like this
{
"17841400714813297": {
"business_discovery": {
"username": "thomasguntenaar",
"media_count": 76,
"id": "17841400714813297"
},
"id": "17841400714813297"
},
"17841403388404550": {
"business_discovery": {
"username": "thomasguntenaar",
"media_count": 76,
"id": "17841400714813297"
},
"id": "17841403388404550"
},
"17841401383243593": {
"business_discovery": {
"username": "thomasguntenaar",
"media_count": 76,
"id": "17841400714813297"
},
"id": "17841401383243593"
}
}
(#803) Some of the aliases you requested do not exist: 17841400714813297,17841403388404550,17841401383243593
Apparently the API thinks this was supposed to be one id, and doesn’t realize it is supposed to be three separate ones.
The API has a syntax to request data for more than one object in one request - instead of /{id}?fields=foo, you can make a request of the form ?ids={1,2,3}&fields=foo, to request this data for the objects with ids 1, 2 and 3 in one go. The resulting data structure will contain a sub-structure for each of those ids.
The same structure should work in batch requests as well, when parts (here, the IG account ids returned by the previous query) are dynamically inserted.

Add event to calendar on SharePoint through REST API

I'm trying to add a calendar event to a SharePoint Calendar through REST API but i can't seems to find the relevant resources to achieve this.
If i understand correctly, the calendar in SharePoint is a List of events object, as such I should be able to add the event via ListItem object?
Sorry if this sounds wrong as I'm not familiar with SharePoint structure.
Thanks
This is the example for OAuth token Authentication but REST part is anyway like this.
var dataObj = {
"Subject": "Birthday Party"
"Body": {
"ContentType": "Text",
"Content": "Birthday Party for Cathy",
},
"Start": {
"dateTime": "2016-07-03T09:00:00Z",
"timeZone": "Asia/Tokyo"
},
"End": {
"dateTime": "2016-07-04T11:00:00Z",
"timeZone": "Asia/Tokyo"
},
"Location": {
"DisplayName": "Conference Room 1"
},
"ShowAs": "Busy",
"Attendees": [
{
"EmailAddress": { "Name": "Alex Darrow", "Address": "darrow.alex#company.com" },
"Type": "Required"
}
]
};
var url = "https://graph.microsoft.com/v1.0/me/events/";
var data = JSON.stringify(dataObj);
$.ajax({
url: url,
type: "POST",
data: data,
beforeSend: function (XMLHttpRequest) {
XMLHttpRequest.setRequestHeader("Accept", "application/json;odata.metadata=full;odata.streaming=true");
XMLHttpRequest.setRequestHeader('Authorization', 'Bearer ' + accessToken);
XMLHttpRequest.setRequestHeader("content-type", "application/json;odata=verbose");
},
success: function (result, textStatus, jqXHR) {
//Success
},
error: function (data) {
//
}});

page-id/notifications returns an empty array

I'm writing a desktop application using Facebook SDK .NET. This app must do somethink for every post, comment or message sent to a Facebook page. I'm using the page-id/notifications API command:
page-id/notifications?fields=id,title,unread,application,from,message,object&limit=250
This command returns correct unseen count in summary section but data array is empty:
{
"data": [
],
"summary": {
"unseen_count": 2,
"updated_time": "2016-02-05T14:53:10+0000"
}
}
If someone write a new wall post on the page or send a private message to the page, unseen_count is updated but data array is always empty. If someoune write a comment to an exisiting wall post unseen_count is updates and data array is populated with a comment notification (only this type of notification are added to data array):
{
"data": [
{
"id": "notif_XXXXXXXXXXXXXXX_XXXXXXXXXXXXXXXX",
"title": "yyyyy yyyyyyy commented on his post.",
"unread": 1,
"application": {
"link": "https://www.facebook.com/games/?app_id=xxxxxxxxxxx",
"name": "Feed Comments",
"id": "1967xxxxxxx"
},
"from": {
"name": "Mxxxx Sxxxxxx",
"id": "1020xxxxxxxxxxxxx"
},
"object": {
"created_time": "2016-02-05T14:52:32+0000",
"message": "ABCDEFGHILMNOPQRSTUVZ",
"id": "36xxxxxxxxxxxx0_546xxxxxxxxxxx0"
},
"to": {
"name": "Ixxxxxxx",
"id": "36xxxxxxxxxxxxx"
}
}
],
"paging": {
"previous": "xxxxxxxxxxxxxxxxxxxxxxxxxx",
"next": "xxxxxxxxxxxxxxxxxxxx
},
"summary": {
"unseen_count": 3,
"updated_time": "2016-02-05T14:55:23+0000"
}
}
Is it an API bug or there is something wrong in my API request?
I CANNOT use real time notification.
Thanks
Marco

GoodData "Create Report Definition" API Call giving 500 Internal Server Error

I'm trying to create a report definition using the GoodData REST API. I use the following endpoint to invoke the rest call.
"/gdc/md/{project-id}/obj"
When i try to invoke the API call with the following dataset in which the projectId and the userId are valid, it gives me the error with the response code 500.
{
"reportDefinition": {
"content": {
"filters": [],
"format": "grid",
"grid": {
"rows": [],
"columns": [
"metricGroup"
],
"sort": {
"columns": [],
"rows": []
},
"columnWidths": [],
"metrics": [
{
"uri": "/gdc/md/qy48iv4flikdlcwpwioizuip74wt8nb5/obj/63f3cecd2a8d3ce2ec9378381c8f39e3",
"alias": ""
}
]
}
},
"meta": {
"title": "Sample report definition",
"summary": "This is a sample report",
"tags": "",
"deprecated": 0,
"category": "samplecategory"
}
}
}
{
"error": {
"message": "Internal server error. Please fill in bug report with request_id='lp78FL5S1IPMqB2n'"
}
}
I'm certain that the user project_id and the user_id are valid. Is this an error in the API?
Thank you in advance.
Apart from the metrics URI that looks weird (hash instead of numeric ID), I was able to dig in our logs an error that says: "Category is not equal to tag structure".
In your example you have its value set to "samplecategory". "category" property defines what type of object are you creating. If you are creating a report definition it should have value of "reportDefinition".
Last time I worked with GoodData API, metrics had numeric IDs. That seems most likely to be the culprit. Where did you get "/gdc/md/qy48iv4flikdlcwpwioizuip74wt8nb5/obj/63f3cecd2a8d3ce2ec9378381c8f39e3" from, especially the "63f3cecd2a8d3ce2ec9378381c8f39e3" part?