jsonapi + ember 2.0 + pagination - ember.js

How to do pagination in latest version of ember-data (v2.2) and a jsonapi backend?
I am in control of the backend implementation so I can implement any strategy, but I would prefer to follow the standard as described here:
http://jsonapi.org/format/#fetching-pagination
However, that description is a bit cryptic to me without an example.
And how to handle that smoothly on the client (ember) side?
Is there some built in stuff in ember-data to process the paging-links?
EDIT:
I guess to get started I must process the meta information. By overriding the serializer. At the time deserialize is called I can read the meta from the payload but at that time I don't have an object to store it on. Later when my object is done deserialized I don't have access to the payload with the meta information.
Does that make sence? Here is my example payload:
{
"data": {
"id": "1",
"type": "user",
"attributes": {
"firstname": "John",
"lastname": "Doe",
"email": "john.doe#example.com",
}
},
"included": [{
"id": "68",
"type": "activity",
"attributes": {
"title": "Yoga",
}
}, {
"id": "65",
"type": "activity",
"attributes": {
"title": "Slalom",
}
}],
"meta": {
"activity-total": "23",
"activity-pagesize": "2",
"activity-offset": "0"
}
}
Where to put my code that reads the meta information and stores it on the user object?

You could use the Ember Infinity Addon. It does all the magic for you.

Related

JSONAPI: Update relationships including attributes

I have a nested object in my SQLAlchemy table, produced with Marshmallow's nested schema feature. For example, an articles object GET response would include an author (a User type) object along with it.
I know that the JSONAPI spec already allows updating relationships. However, often I would like to update an article as well with its nested objects in one call (POST requests of articles that include a new author will automatically create the author). Is it possible to make a PATCH request that includes the resources of a relationship object that doesn't yet exist?
So instead of just this:
PATCH /articles/1 HTTP/1.1
Content-Type: application/vnd.api+json
Accept: application/vnd.api+json
{
"data": {
"type": "articles",
"id": "1",
"relationships": {
"author": {
"data": { "type": "people", "id": "1" }
}
}
}
}
It'd be ideal to pass this in to create a new author if there didn't exist one (this is not my actual use case, but I have a similar real life need):
PATCH /articles/1 HTTP/1.1
Content-Type: application/vnd.api+json
Accept: application/vnd.api+json
{
"data": {
"type": "articles",
"id": "1",
"relationships": {
"author": {
"data": { "type": "people", "id": "1", "attributes": {"name": "new author":, "articles_written": 1} }
}
}
}
}
Is this at all possible or have suggestions on what REST frameworks can support this, or would it be totally against the JSON API spec?
Updating multiple resources at once is not possible with JSON API spec v1.0. But there are several suggestions how to do that. Both official extensions which are not supported anymore aimed to support creating, updating or deleting multiple request at once. Also there is an open pull request which would introduce operations to upcoming JSON API spec v1.2.
For example a request updating two resources at once using suggested operations[1] would look like this:
PATCH /bulk HTTP/1.1
Host: example.org
Content-Type: application/vnd.api+json
{
"operations": [{
"op": "update",
"ref": {
"type": "articles",
"id": "1"
},
"data": {
"type": "articles",
"id": "1",
"attributes": {
"title": "Updated title of articles 1"
}
}
}, {
"op": "update",
"ref": {
"type": "people",
"id": "2"
},
"data": {
"type": "people",
"id": "2",
"attributes": {
"name": "updated name of author 2"
}
}
}]
}
This would update title attribute of article with id 1 and name attribute of person resource with id 2 in a single transaction.
An request to update a to-one relationship and updating the related resource in a singular transaction would look like this:
PATCH /bulk HTTP/1.1
Host: example.org
Content-Type: application/vnd.api+json
{
"operations": [{
"op": "update",
"ref": {
"type": "articles",
"id": "1",
"relationship": "author"
},
"data": {
"type": "people",
"id": "2"
}
}, {
"op": "update",
"ref": {
"type": "people",
"id": "2"
},
"data": {
"type": "people",
"id": "2",
"attributes": {
"name": "updated name of author 2"
}
}
}]
}
This is a request which creates a new person and associate it as author to an existing article with id 1:
PATCH /bulk HTTP/1.1
Host: example.org
Content-Type: application/vnd.api+json
{
"operations": [{
"op": "add",
"ref": {
"type": "people"
},
"data": {
"type": "people",
"lid": "a",
"attributes": {
"name": "name of new person"
}
}
}, {
"op": "update",
"ref": {
"type": "articles",
"id": "1",
"relationship": "author"
},
"data": {
"type": "people",
"lid": "a"
}
}]
}
Note that the order is important. Operations must be performed in order by server. So the resource has to be created before it could be associated to an existing one. To express the relationship we use a local id (lid).
Please note that operations should only be used if a request has to be performed transactionally. If each of the included operations could be executed atomically, singular requests should be used.
Accordingly to implementation list provided on jsonapi.org there are some libraries supporting Patch extension.
Update: Operations were not included in release candidate for JSON API v1.1. It's planned for v1.2 now. The author of the pull request, which is also one of the maintainers of the spec, said that "operations are now the highest priority". A release candidate for v1.2 including Operations may be shipped "RC within a few months of 1.1 final."
[1] Introducing operations to JSON API v1.2 is currently only suggested but not merged. There may be breaking changes. Read the related pull request before implementation.

How to get included values of jsonapi on a router with ember-data?

I'm using jsonapi directives to make a connection between ember.js app and an API. I have a track that could have like 50 or more comments and I need to load them on a route to perform some logic.
This is and example response of the API:
{
"data": {
"id": 1,
"type": "track",
"attributes": {
"name": "XPTO"
},
"relationships": {
"comment": {
"data": [
{"id": 1, "type": "comment"}
]
}
}
},
"include": [
{
"id": 1,
"type": "comment",
"attributes": {
"text": "Lorem ipsum..."
}
}
]
}
Now imagine it with 50 comments, this would be very consuming to make a request for each call. If I do it in a view with an each loop, it doesn't make all the requests, but it I try to access it in a Route, it will make all the requests. How do I achieve that with the following code?
this.store.findRecord('track', 1).then((t) => {
// logic here
// I tried this but it would make all the requests too
t.get('comments');
})
U can use property "coalesceFindRequests" in your adapter
coalesceFindRequests: true
If you set coalesceFindRequests to true it will instead trigger the following request:
GET /comments?ids[]=1&ids[]=2
so this makes only one call for all the comments.
Note: Requests coalescing rely on URL building strategy. So if you
override buildURL in your app groupRecordsForFindMany more likely
should be overridden as well in order for coalescing to work.

Sparse Fieldsets or Reload from Component, for Ember Data 2.0+

We're working on a charting application that, for performance reasons, needs a way to split the chart data from some meta data to render charts to select from.
It doesn't appear that Ember-data (currently v2.5.0) supports JSONAPI's Sparse Fieldsets. Does it?
There are probably other options, like using relationships, but the design that's most intuitive to us right now is to break the spec and use different endpoints for when a chart is queried in a collection:
GET ../charts/
{"data": [{
"type": "charts",
"id": "1",
"attributes": {
"type": "A",
"precision": "10",
"average": "22.2",
"minimum": "20.4",
"maximum": "25.3",
},
{
"type": "charts",
"id": "2",
"attributes": {
"type": "A",
"precision": "100",
"average": "20.0",
"minimum": "10.0",
"maximum": "30.0",
},
...
]}
and properly when queried by ID:
GET ../charts/1
{"data": {
"type": "charts",
"id": "1",
"attributes": {
"type": "A",
"precision": "10",
"average": "22.2",
"minimum": "20.4",
"maximum": "25.3",
"history": [
["100","21.0"],
["200","20.4"],
["300","25.3"],
...
]
}
}
But we haven't found a way to force EmberData to reload the data from the backend service from a Component. We'd like to use the backgroundReload functionality, as we believe that would provide the best visual results, but all documentation about it is done using model hooks from a Route.
Am I on the right track or has someone solved this?
A note of caution for future Googlers -- this is not using actual JSONapi Sparse Fieldsets with fields[chart]=history but is just relying on breaking the JSONapi spec and returning different attributes for each endpoint.
You could inject the store service into the component and forcibly look up that model on hook:
import Ember from 'ember';
export default Ember.Component.extend({
store: Ember.inject.service(),
didReceiveAttrs() {
this._super(...arguments);
this.get('store').findRecord('chart', this.get('chart').id);
},
});
EDIT: Note that this still has caching problems from the ember-data level, in that you may run into scenarios where partial attributes may exist or may not.
EDIT: Switched the hook to didReceiveAttrs

Ember - Sending particular values in PUT request

I have a form which I am using to edit details via form. Ember does a PUT request like required but I need it to only send particular values and not everything within the JSON object. The object is structured as:
{
consoles: {
"id": "1",
"name": "Street Fighter",
"type":"Beat-em-up"
"versions": "10",
"consoles": [
{
"id": "1",
"name": "Microsoft",
"console": "Xbox 360"
},{
"id": "2",
"name": "Microsoft",
"console": "Xbox One"
},{
"id": "3",
"name": "Sony",
"console": "Playstation 4"
}
],
"Characters":[],
"Reviews":[]
}
}
The only editable values within my form are:
name
type
versions
When I press the update button, everything is sent in a PUT request. Is it possible for ONLY name, type and versions to be sent in the request?
I'm aware of overriding updateRecord but I wouldn't know where to start if this was what I needed to do.
You can write your own Serializer to only send specific attributes up to the server.
See the docs here

Where/when should I remove the relationship type to avoid an unknown keys warning?

I'm using Ember Data with a server application that follows the json:api standard. When I normalize the response from the server, I'm adding a relationshipType attribute from the links so that Ember Data knows what type of model to build when the relationship is polymorphic.
For example, here's the response from the server:
{
"members": {
"id": "1",
"created_at": "2014-10-15T18:35:00.000Z",
"updated_at": "2014-10-15T18:35:00.000Z",
"links": {
"user": {
"id": "1",
"type": "users",
"href": "http://test.host/api/v1/users/1"
},
"organization": {
"id": "2",
"type": "customers",
"href": "http://test.host/api/v1/customers/2"
}
}
}
}
The organization relationship is polymorphic, and the type in this instance is customers.
In the Ember application, I'm normalizing the response into following (which follows the RESTSerializer convention):
{
"members": {
"id": "1",
"created_at": "2014-10-15T18:35:00.000Z",
"updated_at": "2014-10-15T18:35:00.000Z",
"user": "1",
"userType": "users",
"organization": "2",
"organizationType": "customers"
}
}
This works, and Ember Data builds the correct user relationship and organization relationship (using the Customer model).
But, I'm receiving the following warning:
WARNING: The payload for '(subclass of DS.Model)' contains these unknown keys:
[userType,organizationType]. Make sure they've been defined in your model.
I'd like to remove these relationshipType keys and their values after they've been used.
Where should I do this?
Have you tried using https://github.com/kurko/ember-json-api? I may have some other overrides in my app to handle polymorphism but hopefully the package will get you closer.
Also see my pending PR.