Is it possible to create a nested adapter?


#1

Am I able to nest Ember Data adapters?

For example, say if I have a model //models/site.js with a template //templates/site.hbs and I want to make a custom query() request to ${ENV.APP.API_HOST}/customers/${org}/sites - as per the docs I can simply customise the query() function at //adapters/site.js.

But what if I have a second template at //templates/sites/show.hbs and I need to query a second distinctly different endpoint such as ${ENV.APP.API_HOST}/customers/${org}/sites/${id} (or any other deeply nested data endpoint) can I setup an adapter under //adapters/sites/show.js? I can’t seem to achieve that with Ember Data currently.


#2

So I was able to customise and fix this by using an ember plugin - https://github.com/amiel/ember-data-url-templates/. It has good documentation and allows you to customise URL segments.

My site adapter:

// adapters/site.js
export default ApplicationAdapter.extend({
  urlTemplate: '{+host}/api/{apiVersion}v1/customers{/org}/sites{/site}',
  queryUrlTemplate: '{+host}/api/{apiVersion}v1/customers{/org}/sites'
});

And my service adapter:

// adapters/service.js
export default ApplicationAdapter.extend({
  urlTemplate: '{+host}/api/{apiVersion}v1/customers{/org}/services{/service}',
});

Then in my routes I loaded params that were picked up by the URL segments in my adapters thanks to ember-data-url-templates. Using seperate queryRecord() calls with Ember store allowed me to specify the correct endpoints as required.

// routes/sites.js
export default Ember.Route.extend({
  model: function(params) {
    let siteQuery = this.modelFor('sites');
    let org = siteQuery.customer_orgCode;
    return RSVP.hash({
      site: this.get('store').queryRecord('site', { org: org, site: params.site_id })
    });
  }
});

// routes/sites/show.js
export default Ember.Route.extend({
  model: function(params) {
    let siteQuery = this.modelFor('sites');
    let org = siteQuery.customer_orgCode;
    return Ember.RSVP.hash({
      service: this.get('store').queryRecord('service', { org: org, service: params.instance_id })
    });
  }
});

NB // I’ve use an RSVP hash as there’s likely to be multiple calls for the same model, but you can just return the this.get query as necessary directly to model: as well.