Load a route's model using data from multiple API sources


#1

I have a route with multiple related models that each need to source data from two different API endpoints. The two endpoints’s data are structured almost identically, but each endpoint provides a couple data points for each model that the other endpoint does not. The endpoints have embedded records that map to my models. I’d like to load data from each of the two endpoints and merge the data together for each of the models, but I’m not sure if this is possible using Ember Data. I’ve found examples of loading multiple models in a single route from different endpoints for each model (using a promise hash), but I’ve come up empty on how to source data for a single (or multiple) models from multiple endpoints. Am I missing something, or is this just not something that is straightforward in Ember/Ember Data?

Here are the two endpoints from MBTA (Boston’s transit agency), one provides scheduled trips any any given bus stop, the other provides only trips with predicted arrivals at any given bus stop (with some additional data). You’ll see that the data and structure is virtually the same between the two endpoints, but the first endpoint (predictionsbystop) provides each trip’s predictions (pre_away, pre_arr_dt, pre_dep_dt, trip_headsign) and a ‘vehicle’ object for each trip. None of these items are provided by the second endpoint (schedulesbystop), which is also needed because it provides a more comprehensive list of trips but gives fewer details about each trip. Basically I need to use schedulesbystop to get the full list of trips at a stop, and then use predictionsbystop to get any available trip predictions and vehicles.

http://realtime.mbta.com/developer/api/v2/predictionsbystop?stop=175&format=json&api_key=wX9NwuHnZU2ToO7GmGR9uw

and

http://realtime.mbta.com/developer/api/v2/schedulebystop?stop=175&format=json&api_key=wX9NwuHnZU2ToO7GmGR9uw

(don’t worry about me giving out my API key, its just a publicly available test key)

Here are my models being populated by data from both of these APIs (The APIs have embedded records, so I’m using ActiveModelAdapter/Serializer and the EmbeddedRecordsMixin).

App.ApplicationAdapter = DS.ActiveModelAdapter.extend({
    host            : 'http://realtime.mbta.com',
    namespace       : 'developer/api/v2'
});

App.StopAdapter = Realtime.ApplicationAdapter.extend({
    pathForType     : function() {return 'schedulebystop';}
});

App.Stop = DS.Model.extend({
    stopId          : DS.attr('string'),
    stopName        : DS.attr('string'),
    mode            : DS.hasMany('mode', { embedded: 'always' })
});

App.Mode = DS.Model.extend({
    routeType       : DS.attr('string'),
    modeName        : DS.attr('string'),
    stop            : DS.hasMany('stop', { embedded: 'always' }),
    rout            : DS.hasMany('rout', { embedded: 'always' })
});

App.Rout = DS.Model.extend({
    routId          : DS.attr('string'),
    routName        : DS.attr('string'),
    mode            : DS.belongsTo('mode', { embedded: 'always' }),
    direction       : DS.hasMany('direction', { embedded: 'always' })
});

App.Direction = DS.Model.extend({
    directionId     : DS.attr('string'),
    directionName   : DS.attr('string'),
    rout            : DS.hasMany('rout', { embedded: 'always' }),
    trip            : DS.hasMany('trip', { embedded: 'always'})
});

App.Trip = DS.Model.extend({
    tripId         : DS.attr('string'),
    tripHeadsign   : DS.attr('string'),
    schDepDt       : DS.attr('string'),
    schTime        : DS.attr('string'),
    preAway        : DS.attr('string'),
    preAwayMin     : DS.attr('string'),
    direction      : DS.belongsTo('direction', { embedded: 'always' })
});