I am creating an API and I need to create a Post which is defined as:
{
"Title": "Blog first post",
"Body": "Some body text for the post",
"PublishedAt": "2016-02-08",
"Category": {
"Id": "20",
"Name": "Travel"
},
"Tags": [
{ "Id": "12", "Name": "Vacation" },
{ "Id": "18", "Name": "Beach" }
]
}
What would you post to the API? The following?
{
"Title": "Blog first post",
"Body": "Some body text for the post",
"PublishedAt": "2016-02-08",
"Category": {
"Id": "20",
},
"Tags": [
{ "Id": "12" },
{ "Id": "18" }
]
}
Or would you do this by steps as follows:
POST /category/20/posts
POST /posts/recently-created-post-id/tags >> Add tags one by one?
But what to do when the entire data is ready to post?
What is the standard for this situations in a REST API?
Depends on how you want to present your API and how thorough you want it to be. I would do the following given your models.
I would have one endpoint at POST /posts and would send the entire body of the post model.
I would also have one endpoint at POST /posts/{id}/tags to allow tags to be submitted after the post is created. So a call to POST /posts/{id}/tags would receive a body of:
{ "Id" : 12 }
For simplicity sake, many people would recommend that you stick to only one level which would mean you would create an endpoint for PUT /posts/{id} or PATCH /posts/{id} and submit your new tags through those endpoints. A PUT request would submit the full body you used in the POST along with any new tags. The purpose of a PUT is to replace the existing post model entirely with the new body. A PATCH request would submit a body that adhere's to a REST PATCH endpoint which allows modifications to an object model without submitting the entire model.
If you were going with the multi-level model, you would need to support PUT and PATCH requests at the endpoint PUT /posts/{id}/tags/{tagid} and PATCH /posts/{id}/tags/{tagid}. Since your tags only contain a reference id, PUT and PATCH does not make sense because all you want to do is add or delete tags.
I assume you would also need to handle tag deletions. With the one level endpoint approach, you would submit the entire post model without the tag you wanted to remove via a PUT request to /posts/{id}. For example, if you wanted to delete tag 12 your :
{
"Title": "Blog first post",
"Body": "Some body text for the post",
"PublishedAt": "2016-02-08",
"Category": {
"Id": "20",
},
"Tags": [
{ "Id": "18" }
]
}
If you wanted to go with the multi-level approach, you would issue a DELETE request to /posts/{id}/tags/12.
There's no hard and fast rule for these situations in REST.
If we assume that the client wants to create everything in one go and wait the least amount of time possible for a response, common sense would suggest keeping everything in one request to avoid (a)synchronicity problems between the main POST and POSTs for the tags.
Related
I've found this example that is using the Catalog URL Reference for populating custom slots in Alexa Skill.
The problem is that I don't know how to populate this catalog.
I was able to create the model catalog using ask cli like this:
ask api create-model-catalog -n catalog_name -d "description"
That produces me the catalogId in the form "catalogId" : "amzn1.ask.interactionModel.catalog.blabla" like the one in the GitHub example in the first link.
The problem is that I don't know how to put the values (for example the ingredients.json in the above example) inside that catalog.
I've tried using
ask api create-model-catalog-version -c catalogId -f ingredients.json
But what I obtain is
Call create-model-catalog-version error.
Error code: 400
{
"message": "Request is not valid.",
"violations": [
{
"message": "'source' field of the request is invalid."
}
]
}
In the documentation, there isn't an example of how to deal with this so I'm stuck at this point.
Thanks for your help
In order to create and use a catalog in your alexa skill, you have to:
Upload the catalog file into a bucket or another public storage endpoint.
After that, you have to specify a JSON file with the following content (eg. catalog.json):
{
"type": "URL",
"url": "[your catalog url]"
}
Use the ask api to create the catalog, as you mentioned, to get your catalog-id:
ask api create-model-catalog --catalog-name "IngredientsCatalog"
--catalog-description "Ingredients"
Create a model catalog version by using the file that contains your catalog URL:
ask api create-model-catalog-version --file .\catalog.json --catalog-id [your catalog-id]
This call will provide a command to track the create version status. Something like:
ask api get-model-catalog-update-status -c [your catalog-id] -u [request id]
If the version has been created successfully, then you can set it on your skill interaction model:
"types": [
{
"name": "Ingredient",
"valueSupplier": {
"type": "CatalogValueSupplier",
"valueCatalog": {
"catalogId": "[your catalog-id]",
"version": "[the desired version number]"
}
}
}
]
I can add a little more here that may be helpful:
In step 1 in the answer above, from my testing the S3 bucket must be public. Also, below is the format of the JSON that you will want to use, including the use of synonyms which is not described in the official Amazon example. Note that you don't have to include an ID as shown in that example.
{
"values": [
{
"name": {
"value": "hair salon",
"synonyms": [
"hairdresser",
"beauty parlor"
]
}
},
{
"name": {
"value": "hospital",
"synonyms": [
"emergency room",
"clinic"
]
}
},
]
}
I will implement my fan out model in Google's Firebase, but my question is only theoretical so the answer doesn't need to be in Firebase terms.
I am creating an app that I think should have a data structure similar to Tinder. The idea is only one post shows in your feed at a time; you then accept it or reject it and another one pops up and so on. My question is how exactly to structure the data so that it remains fast when the app scales up.
What I have right now is one node called "Posts" that contains every post that has ever been made. The app then queries for a post which is checked against the user Node of "viewedPosts" so that if the queried post has already been accepted/rejected by the user another one is queried until an unseen one is found. This obviously isn't a great solution because if there are a lot of posts, a query through them will be slow (especially if a lot of them have already been seen and the query has to be repeated multiple times).
I came across this article: The Firebase Blog: Client-side fan-out for data consistency which gave me the idea of creating a node inside each user which is "unseen posts" and every time a new post is uploaded by someone, to put it in the unseen folder for every user. This solves the problem on the side of the viewer, but to upload, one would have to download the list of all users in the app and then write to every single one of them.
So the question is, is there a middle ground between these which I can use to accurately do this?
Thank you.
EDIT:
Someone asked for my data structure:
{
"posts": {
"jkldsahjfkds": {
"title": "Simple Post",
"description": "This is my first post",
"numberOfImages": "2",
"price": "14.99",
"timestamp": "51782345",
"postedBy": "-hjd673bbewi7n",
"name": "Ryan Jacobs"
}
"-nisd7enskwes" : {...}
"-asdjfhk7385i" : {...}
"-sdfh49506ndk" : {...}
}
"users": {
"user1": {
"postsViewed": {
"-nisd7enskwes": 51784645,
"-sdfh49506ndk": 51782329
}
"postsLiked": {
"-sdfh49506ndk": 51782329
}
"userData": {
"name": "Albert Jones",
"bio": "Hi! Jow is everyone doing!?",
"location": "London"
}
}
}
}
Say I have an API endpoint at /users and another one at /cars. Naturally, a GET request to either of them will get all users or cars available. Now, a GET /users/74/cars should return all cars belonging to user 74.
But my app has many models related to cars, not just users, so more endpoints exist like /shops/34/cars and /mechanics/12/cars. For simplicity, I want all PUT/PATCH requests to be made to the main /cars endpoint.
At the moment of performing the save, Restangular will by default do a PUT request to the endpoint through which the item was loaded. But that endpoint do not exist.
It also provides a nice Restangular.setParentless(['cars']) method that will discard the first part of the url. However, I don't want to do this globally, but specifically for a particular element.
The neatest would actually do it globally, but restrict it for a specific method, like: Restangular.setParentless(['cars'], ['PUT']).
Anything like that around? Or am I overcomplicating it?
So far I tried stuff I don't like:
delete car.parentResource;
I would recommend using self reference links. A self reference link is a link which stores the route which should be used for GET/PUT/DELETE etc. on the item, rather than the URL from which it was pulled.
Example, update the mileage on one of user id 74's cars:
First, configure Restangular to look for a self link property called 'self' on each object.
RestangularProvider.setRestangularFields({
selfLink: 'self'
});
Next, make your call to get the cars. I'll assume that you have already modified your API to return a property called 'self' on each object that has the URL to it's proper API endpoint.
GET /users/74/cars
[
{
"id": 12,
"model": "Camaro",
"make": "Chevrolet",
"year": 1969,
"color": "red",
"odometer": 67294,
"license": "ABC12345",
"self": "/cars/12"
},
{
"id": 14,
"model": "Gallardo",
"make": "Lamborghini",
"year": 2015,
"color": "black",
"odometer": 521,
"license": "XYZ34567",
"self": "/cars/14"
}
]
We want to add some miles to one of them, and then save it. The entire Restangular code would look like:
Restangular.one('users', 74).all('cars').getList().then(function(cars){
cars[1].odometer = 613;
cars[1].put();
});
The PUT will go to /cars/14 instead of /users/74/cars/14. This is very useful for applications like yours that relate models as a graph rather than a strict hierarchical tree.
Hi I have got the following method which fetches the JSON data
$("#Result").click(function () {
$.ajax({
type: "POST",
url: "SampleWebForm.aspx/FetchLibraryDetails",
data: "{}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (data) {
// Replace the div's content with the page method's return.
$("#Result").text(msg.resources.description.title);
}
});
});
The JSON result from the call is as below
LibraryData{
"resources": {
"description": {
"title": "Getting started with the online library",
"body": "The online library contains amazing resources and can seem overwhelming. This guide gives a very basic introduction. Over your years of study with us you will learn a lot more about resources and how to find and manage them.",
"image": "http:\/\/www.testWebsite.com\/library\/files\/library\/imagecache\/node_standard\/web-journal%20shelves.JPG",
"link": "http:\/\/www.testWebsite.com\/library\/node\/91194"
},
"items": [{
"title": "Large-scale open innovation: open source vs. patent pools",
"body": "Thierry Rayna (2010), 'Large-scale open innovation: open source vs. patent pools', International Journal of Technology Management, vol. 52, no. 3\/4, pp:477-0",
"image": "http:\/\/www.testWebsite.com\/libraryservices\/covers\/?id=0140-6736",
"link": "http:\/\/www.testWebsite.com\/libraryservices\/resource\/article:7477"
},
{
"title": "Introduction to Library Services",
"body": "A great introductory session that will explore the online library. You will know how to find information in your subject and be shown some key resources and services to help with your studies.",
"image": "http:\/\/www.testWebsite.com\/library\/files\/library\/imagecache\/node_standard\/web-journal%20shelves.JPG",
"link": "http:\/\/www.testWebsite.com\/library\/node\/97689"
}]
},
"access": {
"items": [{
"title": "Large-scale open innovation: open source vs. patent pools",
"body": "Thierry Rayna (2010), 'Large-scale open innovation: open source vs. patent pools', International Journal of Technology Management, vol. 52, no. 3\/4, pp:477-0",
"image": "http:\/\/www.testWebsite.com\/libraryservices\/covers\/?id=0140-6736",
"link": "http:\/\/www.testWebsite.com\/libraryservices\/resource\/article:7477"
},
{
"title": "Getting started with the online library",
"body": "The online library contains amazing resources and can seem overwhelming. This guide gives a very basic introduction. Over your years of study with us you will learn a lot more about resources and how to find and manage them.",
"image": "http:\/\/www.testWebsite.com\/library\/files\/library\/imagecache\/node_standard\/web-journal%20shelves.JPG",
"link": "http:\/\/www.testWebsite.com\/library\/node\/91194"
}],
"description": {
"title": "Getting started with the online library",
"body": "The online library contains amazing resources and can seem overwhelming. This guide gives a very basic introduction. Over your years of study with us you will learn a lot more about resources and how to find and manage them.",
"image": "http:\/\/www.testWebsite.com\/library\/files\/library\/imagecache\/node_standard\/web-journal%20shelves.JPG",
"link": "http:\/\/www.testWebsite.com\/library\/node\/91194"
}
},
"search": {
"items": [{
"title": "Large-scale open innovation: open source vs. patent pools",
"body": "Thierry Rayna (2010), 'Large-scale open innovation: open source vs. patent pools', International Journal of Technology Management, vol. 52, no. 3\/4, pp:477-0",
"image": "http:\/\/www.testWebsite.com\/libraryservices\/covers\/?id=0140-6736",
"link": "http:\/\/www.testWebsite.com\/libraryservices\/resource\/article:7477"
},
{
"title": "Getting started with the online library",
"body": "The online library contains amazing resources and can seem overwhelming. This guide gives a very basic introduction. Over your years of study with us you will learn a lot more about resources and how to find and manage them.",
"image": "http:\/\/www.testWebsite.com\/library\/files\/library\/imagecache\/node_standard\/web-journal%20shelves.JPG",
"link": "http:\/\/www.testWebsite.com\/library\/node\/91194"
}],
"description": {
"title": "Getting started with the online library",
"body": "The online library contains amazing resources and can seem overwhelming. This guide gives a very basic introduction. Over your years of study with us you will learn a lot more about resources and how to find and manage them.",
"image": "http:\/\/www.testWebsite.com\/library\/files\/library\/imagecache\/node_standard\/web-journal%20shelves.JPG",
"link": "http:\/\/www.testWebsite.com\/library\/node\/91194"
}
},
"helpdesk": {
"items": [{
"title": "Large-scale open innovation: open source vs. patent pools",
"body": "Thierry Rayna (2010), 'Large-scale open innovation: open source vs. patent pools', International Journal of Technology Management, vol. 52, no. 3\/4, pp:477-0",
"image": "http:\/\/www.testWebsite.com\/libraryservices\/covers\/?id=0140-6736",
"link": "http:\/\/www.testWebsite.com\/libraryservices\/resource\/article:7477"
},
{
"title": "Getting started with the online library",
"body": "The online library contains amazing resources and can seem overwhelming. This guide gives a very basic introduction. Over your years of study with us you will learn a lot more about resources and how to find and manage them.",
"image": "http:\/\/www.testWebsite.com\/library\/files\/library\/imagecache\/node_standard\/web-journal%20shelves.JPG",
"link": "http:\/\/www.testWebsite.com\/library\/node\/91194"
}],
"description": {
"title": "Getting started with the online library",
"body": "The online library contains amazing resources and can seem overwhelming. This guide gives a very basic introduction. Over your years of study with us you will learn a lot more about resources and how to find and manage them.",
"image": "http:\/\/www.testWebsite.com\/library\/files\/library\/imagecache\/node_standard\/web-journal%20shelves.JPG",
"link": "http:\/\/www.testWebsite.com\/library\/node\/91194"
}
}
}
My Question
Basically I am getting a set of JSON data (as above) on to the "data" object.
While debugging I can see the whole json data in the "data" object and can write on to a div tag using “data.d”
But I want to display the data separately from the JSON result Like
4 DIVs resources, access, search & helpdesk.
Under each of these I want to display the corresponding Description and items (each having title, body, image and link).
You have several different options, you can loop through the json object and hand roll some html to do what you want.
or - a much better way would be to use a library that supports templates like Knockout or Angular
If all you need is templates I would go with something like Knockout
Check out the Note 2 example - Using "foreach" option with named template
I personally like Angular, however it may be overkill for your situation
You can iterate over your Object and append some HTML-Element with propertys or Key-Value-Pairs like:
for (var key in obj) {
// do something
if (obj.hasOwnProperty(key)) {
// do somthing else
}
}
I'm trying to get a grip on Ext.direct. On the official page there is this description of the API:
The purpose of the API component of the Ext Direct stack is to output the method configurations for Ext Direct to create client-side stubs. By generating these proxy methods, we can seamlessly call server-side methods as if they were client-side methods without worrying about the interactions between the client and server-side.
I just don't quite get what it means by ...to output the method configurations for Ext Direct to create client-side stubs. Would someone care to explain what this means at a grassroots level?
This will make more sense if you look at the output from the api.php resource included in the following example.
Note that this is being loaded on the page as a <script/> tag, ie:
<script type="text/javascript" src="php/api.php"></script>
When you open the src link you'll see the following JavaScript being generated by server-side PHP (see block of javascript code below).
In other words, PHP is doing the bit where it ... output(s) the method configurations for Ext Direct to create client-side (ie JavaScript) stubs.
Now the next question you should be asking if you want to make sense of this is: Why bother generating client side JavaScript using server side PHP (or other language of choice)?.
Ext.ns("Ext.app");
Ext.app.REMOTING_API={
"url": "php\/router.php",
"type": "remoting",
"actions": {
"TestAction": [{
"name": "doEcho",
"len": 1
}, {
"name": "multiply",
"len": 1
}, {
"name": "getTree",
"len": 1
}, {
"name": "getGrid",
"len": 1
}, {
"name": "showDetails",
"params": [
"firstName",
"lastName",
"age"
]
}],
"Profile": [{
"name": "getBasicInfo",
"len": 2
}, {
"name": "getPhoneInfo",
"len": 1
}, {
"name": "getLocationInfo",
"len": 1
}, {
"name": "updateBasicInfo",
"len": 0,
"formHandler": true
}]
}
};
This seems to be mimicking the way a WSDL works in that it can provide a service description and list all the options available for quering. In other words: Ext.Direct API is taking a concept from SOAP and applying it to a Javascript setting.
The back-end contains the API so this is the easiest place to generate a service definition with all the method names and signatures. Once the Ext.Direct API method stubs are provided (in the back-end), the front-end Ext.Direct library will do the plumbing and turn these into actual functionality that can be queried and used in JavaScript. Much in the same way as SOAP proxy classes can be automatically generated (in PHP/C# or Java) using the WSDL.
Personally I think this is a bit too airy-fairy for my liking. Most APIs are pretty straight forward and trying to implement something akin to WSDL actually makes consumption a lot harder than it would be if you just talk to it directly.