As I'm preparing for my EmberConf presentation about "Loading data patterns with JSON API" I realized there are several areas (JSON API features) where Ember Data could go further and provide a more seamless integration between Ember's data layer and the (JSON) API server.
One example of where this integration is already done is the include
parameter that can be passed to store.findAll
and
store.findRecord
.
On the other hand, here are a few ones where I think ED could provide a tighter integration:
\1. Querying relationships
In my example, I want to be able to search songs belonging to a certain band. JSON API makes it possible to filter relationships just as it can filter top-level type collections. With ED, I currently have to do:
store.query('song', { searchTerm: 'perfect', bandId: band.id });
And then I have to assemble the URL in the adapter layer:
// app/adapters/song.js
import ApplicationAdapter from './application';
export default ApplicationAdapter.extend({
urlForQuery(params) {
let { q, bandId } = params;
delete params.q;
delete params.bandId;
return this.buildURL('bands', bandId) + '/songs?filter[title]=' + q;
}
});
Ideally, I could query the relationship directly in ED:
band.hasMany('songs').query({ filter: { title: 'perfect' } });
\2. Sorting
JSON API supports the sorting of both collections and relationships.
With ED, I'm again back to URL building in the adapter layer which gets the job done but I wonder if a tighter integration is possible/desirable, something like:
store.findAll('band', { sort: '-name' });
I currently do this:
// app/adapters/band.js
import ApplicationAdapter from './application';
export default ApplicationAdapter.extend({
urlForFindAll(modelName) {
return this.buildURL(modelName) + '?sort=name';
}
});
\3. Pagination
In JSON API, page parameters (page[number]
and page[size]
, or page[offset]
and page[limit]
, etc.) should be used.
Here, the details of the server implementation are left for the developers (page-based, offset-based, etc.) but I feel like ED
could go some way towards making it easier on the Ember side-things.
Here is what I currently do:
// app/adapters/song.js
import ApplicationAdapter from './application';
export default ApplicationAdapter.extend({
urlForQuery(params) {
let { pageNumber, pageSize } = params;
delete params.pageNumber;
delete params.pageSize;
let urlParams = `page[number]=${pageNumber}&page[size]=${pageSize}`;
return `${this.buildURL('bands', bandId)}/songs?${urlParams}`;
}
});
A potential ED method could be:
store.query('song', { pageNumber: 2, pageSize: 25 })
or, when paginating relationships (see above):
band.hasMany('songs').query({ pageNumber: 2, pageSize: 25 });
Please don't take this as complaining, or, potentially even worse, demanding that things be done a certain way.
I'm more interested to see the thinking of the core team, the design philosophy when deciding how to address certain things (new features), or whether to address them at all.