Ember Model RESTAdapter nested endpoint - rest

I'm building a web app using Ember 1.5 and I use Ember Model 0.0.11 to link the app to an API. I'm currently having trouble getting Ember Model to use nested API endpoints.
For instance, my app has a User model, which has a hasMany relationship with a Post model. Now, when I want to load the posts for a certain user, I'd like the Post.findQuery('user_id', {user_id}); method to access the GET /users/{user_id}/posts endpoint. Instead, it seems that the Ember Model solution prefers to send the query as a parameter to the GET /posts endpoint.
Ember Model's RESTAdapter does allow for easy customization, but before I start coding a completely custom RESTAdapter I'd love to know if someone has already done this and how they solved the problem.

The solution for us to handle nested API routes was to have a links hash returned with the requested payload. If you can change the API output, this is the way to go for now. For example, when requesting a workspace, the returned JSON looks like this (excuse the escaped characters):
{
"data":
{
"object":"workspace",
"id":"wrk_krVZWGaJ",
"organization_name":"Legros, Klein and Boehm",
"workspace_name":"Legros, Klein and Boehm",
"workspace_path":"legros, klein and boehm",
"status":true,
"credit_production":7,
"credit_revision":16,
"links":{
"projects":"\/v1\/workspaces\/wrk_krVZWGaJ\/projects",
"productions":"\/v1\/workspaces\/wrk_krVZWGaJ\/productions",
"subscription":"\/v1\/workspaces\/wrk_krVZWGaJ\/subscription",
"assets":"\/v1\/workspaces\/wrk_krVZWGaJ\/assets",
"descriptions":"\/v1\/workspaces\/wrk_krVZWGaJ\/descriptions",
"roles":"\/v1\/workspaces\/wrk_krVZWGaJ\/roles",
"registrations":"\/v1\/workspaces\/wrk_krVZWGaJ\/registrations",
"users":"\/v1\/workspaces\/wrk_krVZWGaJ\/users"
}
}
}
The model defines the links as async hasMany relationships, i.e. DS.attr('projects', {async: true}). When the workspace is loaded from the store, the linked projects aren't included. When you use {{#each workspace.projects}} or workspace.get('projects') anywhere else, ember-data will make a GET request to /v1/workspaces/wrk_krVZWGaJ/projects/, rather than the default route of /projects/. Neato, eh?
More details on the RESTAdapter findHasMany method.

Related

How do I get the Explore and Stream section from the SoundCloud API

I can't seem to find the section in their api reference. I tried it as a searchquery but it doesn't seem to work. api.soundcloud.com/stream or /explore return a 404, so that doesn't work either
Thats actually not a part of the public API.
But its quite easy to grab your call from the dev console.
Thats an example call from my user:
https://api-v2.soundcloud.com/stream?user_id=e87647259112403eaa239b6e2c510e46&sc_a_id=e87647259112403eaa239b6e2c510e46&user_urn=soundcloud%3Ausers%3A1672444&promoted_playlist=true&limit=10&offset=0&linked_partitioning=1&client_id=02gUJC0hH2ct1EGOcYXQIzRFU91c72Ea&app_version=a089efd
To make that call work, you need to modify the headers.
These answers may help you:
Retrieving the "recommended" playlist via API call?
soundcloud: Is api-v2 allowed to be used and is there documentation on it?
How to get "all" tracks related to an artist with Souncloud API
Using these endpoints does not go inline with SoundClouds TOS.

CakePHP 3 allow only REST index.json and and.json (no normal views) with Auth

I've created the blog from blog tutorial, and I would to protect articles list, but I want that this be accesible across REST, I've activated json extensions.
All works well. I can add and retrieve list, but now I want to deny index and add from web and only be accesible from .json to public.
I tried with
public function beforeFilter(Event $event)
{
parent::beforeFilter($event);
$this->Auth->allow('index.json');
}
But this obviously doesn't work. All webpage is login protected as is in tutorial. Web services should be accesible to Android App (code is ready and working).
Thank you!
Of course that doesn't work, the allow() methods expects valid method names, and that's all the authentication component cares about, method/action names, it doesn't matter how the action was requested.
What you are trying to do requires you to check the type of the request, and based on the results, allow the actions. Checking the request type can be done using Request::is().
See Cookbook > Request & Response Objects > Checking Request Conditions
So it might be as simple as
if ($this->request->is('json')) {
$this->Auth->allow(['index', 'add']);
}

Proper way to structure my REST api in this case

I am trying to build a little web application with the MEAN stack (MongoDB, ExpressJS, AngularJS and NodeJS).
My question is very simple. If you take the example of a blog, it will contains blog posts, that you could list at this url:
GET /api/posts
You could also get the comments for that posts:
GET /api/posts/:postId/comments
and get a single comment:
GET /api/posts/:postId/comments/:commentId
The relation between post and comment is really obvious here, but does it still makes it mandatory to have it this way? or could I just perform my CRUD operations through /api/comments? In the end, a comment object in mongodb will always have a postId attribute anyway which will reference the post that it is related to... Moreover, the API will not be exposed and is strictly meant to be used by the application.
does it still makes it mandatory to have it this way?
No. This is not mandatory at all.
or could I just perform my CRUD operations through /api/comments?
Yes. This will result in cleaner resources URIs (endpoints).
You can also get post-specific comments with:
GET /api/comments?postId={postId}
Further, you could also drop the /api prefix if you are serving only an API at the given host.

Where does related logic go on model creation when working with REST api with Django, Backbone, and Tastypie?

We are trying to move some of our app to use backbone and tastypie. I have the REST api set up and it is working on some basic examples. However, there are a few issues where currently we post an ajax request to a custom url, and in that view do a few things like
make related objects
call a few related functions
However, now that I've switched some of this functionality to using backbone and the REST api, I'm not sure where all of that should go!
For example, I had a view to make a Message, and when I made a Message, I also made a Notification and called a function to add some points to the user. Something like
def ajax_send_message(request):
## ... set up some variables ...
## Make the new message
message = Message(user=user, content=message)
message.save()
## Make the notification
notification = Notification(message=message)
notification.save()
## Give the user points
user.add_points_for_message();
return json_response({"status": "ok"})
Now--am I just supposed to do this all in JavaScript? I have a Message Backbone model as well.
// Create message backbone object
var msg = new Message({content:content, user: user});
// Post to server
msg.save();
// Add to backbone collection
messages.add(msg);
I've looked at different parts of tastypie, and it seems you can create custom URL endpoints, and also do validation, but that doesnt seem like the right spot to call related methods. It seems that calling related methods goes against the REST part of it---but then where are they supposed to go?
If I want to add some logic to backbone only when an object is created, where does that go?
The first thing I would suggest is to switch your mindset to an event-based model, where your code reacts to events. In your example above, you save the model to the server then immediately dd it to the collection. How do you even know that the model was saved correctly? That procedural style of programming works better in a synchronous, server-side style of programming.
In the asynchronous world of client-side programming, you make a request and then set up callbacks which determine what will happen next, depending on the events your are listening for. In your case, you want to react a certain way when the message is saved successfully, correct? You can define a success callback for your save operation like so:
msg.save({
success: function(model, response, options) {
messages.add(model);
// code to add notification
// code to add points
}
});
Basically, you are saying "I would like to save this model, and then listen for a success event. When the event comes in, execute the following code." Notice also that I am adding the model returned from the API to the collection, since this is the exact object that was persisted to the server so it's more appropriate to add than the model you created.

OpenGraph: how can i specify a filter in FB.api?

I have built a Facebook app using OpenGraph that permits the users to write reviews on concerts, so that I've defined a concert_id attribute on which the user can insert a review.
Now I would like to show all the reviews inserted for a certain concert_id but cannot find a way. If I do (in JS)
FB.api('/me/MY_APP:action', { limit: 0}, function(response) {
console.log(response);
});
I get all items. This app has to be consumed by mobile, I think it is bad to get all items and, then, filtering only the concert_id i need. What do I have to do to apply a where condition in OpenGraph to a custom action?
As far as I can tell from the API and the Facebook developer pages, it's not possible to filter a call by custom action property using the public Open Graph API.
Two options I can think of:
Option 1:
Implement the category filter by creating custom category objects:
if "review" is a custom action and
GET https://graph.facebook.com/me/[name_space]:review
returns all review actions then
GET https://graph.facebook.com/me/[name_space]:review/scifi_movie
GET https://graph.facebook.com/me/[name_space]:review/action_movie
return actions specific to movie type, where scifi_movie and action_movie are custom objects. You would need to create one object type for each category.
Option 2:
Implement a custom action for each category, e.g.
review_scifi_movie
review_action_movie
These are not particularly elegant solutions but perhaps useful as a hack if nothing else works and you really don't want to do filtering on client side.
The Facebook API will not return individual published objects for a particular action, but that's not your only problem. By the look of it, you're trying to bring in ALL the reviews given for a concert, right? (Meaning those by other users too).
The "/me/" part of the Facebook API call will only return those published actions made by the user that is currently logged in. That won't work for you, as you want those of all your users
The only suggestion I can give is to create a simple web service, where you store all the reviews given for the various concerts. Use this service to pull in reviews given for a particular concert. (I use a similar methodology for reviews in an app of my own).
I dont understand javascript or opengraph..
But when I required in JAVA to fetch reviews made by any user I have used FQL for that and It retrived me all the reviews and FQL also used to fetch all the tables related to Facebook.
I don't think that you can pull that off with the JS SDK.
You can do that in your server though, and since this is a mobile app (or has a mobile version) then that's another good reason to remove this from the client responsibility.
In the server side you can ask facebook for the published actions as you posted, filter them and then return the response.
Another thing that you can do is to save each published action in your db (on each action post you should get an id back from facebook, just persist that) and then you can easily filter the published actions according to what ever criteria you want/need (since you are no longer restricted by the facebook api).
The open graph thing is still pretty new and not tat mature, for example you can't use FQL with it, something that could have been handy for your case.
Regardless though I think that a server solution is best for calculations when mobile is concerned.
i don't know exactly but try this
if (session.authResponse) {
FB.api('/me', {
fields: 'name, picture' // here mention your fields
},
function(response) {
if (!response.error) {
//here response value
});