public
Last active

Per-Type Adapters Proposal

  • Download Gist
gistfile1.md
Markdown

Per-Type Adapter Hooks

Requirements

Many existing JSON APIs are not consistent between types. As JSON endpoints grew organically and were built by different engineers at different times, the style in which records are represented can vary wildly.

Historically, we have asked adapter authors to rely on the fact that the type of record is provided to all adapter hooks (either by passing a type argument, or by passing a record whose constructor can be used) to decide when to use different URLs or serializers.

While this approach works, it tends to lead to complicated and noisy code that is annoying to write:

find: function(store, type, id) {
  if (type === App.Post) {
    $.ajax('/enterprise_cms/v134uu5/db-legacy/posts_endpoint-v2/'+id, 'GET', {
      success: function(json) {
        store.load(type, json);
      }
    });
  } else if (type === App.Comment) {
    $.ajax('/comments/'+id, 'GET', {
      success: function(json) {
        store.load(type, json);
      }
    });
  }
  // ...more conditionals here
}

Users should be able to specify adapters and serializers on a per-type basis, to remove the need for these ugly, monolithic conditionals.

Proposal

Now, instead of specifying a single adapter for the store, multiple adapters can be registered. Each adapter is associated with one or more types, like this:

// Types can be specified as either strings or classes
DS.Store.registerAdapter(['App.Post', 'App.Comment'], DS.Adapter.extend({
  find: function(store, type, id) {
    $.ajax(this.buildURL(type), 'GET', {
      success: function(json) {
        store.load(type, json);
      }
    });
  }
}));

DS.Store.registerAdapter('App.LegacyModel', DS.Adapter.extend({
  find: function(store, type, id) {
    $.ajax('/crazy-larrys-java-api/iamondrugs/this-url_is&so-long?id='+id, 'GET', {
      success: function(json) {
        store.load(type, json);
      }
    });
  }
}));

You can still specify a default adapter for the store by using the existing syntax:

App.Store = DS.Store.extend({
  adapter: 'App.MyAdapter'
});

This default adapter will be used as a fallback if you try to load a record that does not have an adapter specified for its type.

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.