Skip to content

Instantly share code, notes, and snippets.

@tomdale
Created November 2, 2012 23:10
Show Gist options
  • Star 17 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save tomdale/4004913 to your computer and use it in GitHub Desktop.
Save tomdale/4004913 to your computer and use it in GitHub Desktop.
Per-Type Adapters Proposal

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.

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