Serializing data with an API that doesn't provide all the info


#1

I’m trying to get my Ember app working with a REST API (using DS.RESTAdapter) that I don’t have direct control over, so I can’t easily make it fit the standards that Ember works out-of-the-box with (I say easily because I don’t believe the developers for the API have bandwidth to make these changes to fit my needs currently). So I will need to write a serializer and/or adapter for this, but I’m not sure how to go about this.

My models are a bit more complicated than this, but simplicity’s sake, here are the relevant parts of two models:

properties:

name: DS.attr('string'),
locations: DS.hasMany('locations', { async: true })

locations:

name: DS.attr('string'),
locations: DS.hasMany('properties')

The REST API is a bit ugly. I can get all the properties via /api/properties, which returns:

{ "properties": [{ "id": "prop1", "name": "Prop1" }, { "id": "prop2", "name": "Prop 2" }]

But as you can see, it doesn’t return all the locations the properties belong to. For that, I have to make individual calls on a per-property basis. For example: /api/locations?property=prop1, which will then return:

{ "locations": [{ "id": "location1", "name": "Location 1", "id": "location2", "name": "Location 2" }]

Like properties, there is no information in the response of what properties a location belongs to (since the property is already in the URL portion). The API does not support retrieving every location for every property in one call. So is it possible to write an adapter/serializer that will properly map property-location relationships given the above responses? Or would it just be easier to forgo using Ember Data at least for locations and just make REST calls whenever I need a property’s locations?


#2

Is there a typo in your locations model? Do you mean that a location belongs to a property instead of having many properties?:

name: DS.attr('string'),
property: DS.belongsTo('property')

#3

@accelerate I think a good way to handle this is to use the links property to create the association between individual Properties and Locations. In a serializer, normalize each Property to contain a links property that points to that URL. Something like this:

export default DS.RESTSerializer.extend({
  normalizeFindAllResponse(store, primaryModelClass, payload, id, requestType) {
    payload.properties.forEach((property) => {
      property.links = {
        locations: `/api/locations?property=${property.id}`
      };
    });

    return this._super(...arguments);
  }
});

I wrote about it recently here: http://thejsguy.com/2016/02/21/handling-nested-resources-in-ember-data.html