Skip to content

Instantly share code, notes, and snippets.

@balinterdi
Last active February 24, 2017 14:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save balinterdi/e9afd575c2972a3b6e9a3175aaa59338 to your computer and use it in GitHub Desktop.
Save balinterdi/e9afd575c2972a3b6e9a3175aaa59338 to your computer and use it in GitHub Desktop.
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: 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment