Skip to content

Instantly share code, notes, and snippets.

@balinterdi balinterdi/
Last active Feb 24, 2017

What would you like to do?
First-class support for JSON API features in Ember Data

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: });

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.