Properties for nested models with foreign keys


#1

I am implementing a column sort for a model that nests another model that has a foreign key, and I’m stuck not being able to get properties I can pass into the sort. My data looks like this:

var locations = [
  {
    id: 130049,
    name: "MyStore",
    completion_percentages: [
      { "campaign": "1", "completion": 0 },
      { "campaign": "2", "completion": 100 },
      { "campaign": "3", "completion": 68 }
    ],
...
  },
  ...
}
var campaigns = [
  {
    id: 1,
    name: 'Campaign One',
    beginAt: '2016-01-14'
  },
 ...
  {
    id: 3,
    name: 'Campaign Three',
    beginAt: '2016-02-03'
  }
];

The location and campaign queries are both run from the component that displays the locations.

In the component, there’s a Location column for the completion value for each campaign ID. So the user needs to be able to, say, click on “Campaign One” in the header and sort the locations by the completion values for campaign 1.

The Location model looks like this:

Location = DS.Model.extend
  name: DS.attr()
...
  completionPercentages: DS.attr()
...

  completionVal: (campaign_id) ->
    obj = @get('completionPercentage').findBy('campaign_id', campaign_id)
    if obj
      val = parseInt obj['completion']
      if NaN(val)
        -1
      else
        val
    else -1

`export default Location`

I have declared completionPercentages: DS.attr() in the Location model and this has worked for other parts of the app, but I certainly can’t get a property for any of the completion values within this based on the campaign ID, because we don’t know the campaign IDs until runtime.

At first I thought to sort by a function pointer I pass in. But there is already a property sort for other columns in the row, so I need a property. You pass in a function pointer and it tries to parse it as a string.

I thought of creating an afterModel hook on the route, but there’s only one route, and it loads a different model, and the campaign and location queries are invoked by components. I tried generating the dynamic Location properties within the component’s didReceiveAttrs hook but I couldn’t access the Location model. I thought of creating dynamic properties from the component after it loads the campaigns and the locations, but when I try to access the Location model (not instance), I can’t.

I considered using EmbeddedRecordMixin, but there are at most only three campaigns, and they are quickly got from their own query, so I don’t want to sideload them.

In trying different solutions, I have tried a CompletionPercentage model that looked like this:

`import DS from 'ember-data'`

CompletionPercentage = DS.Model.extend
  campaign: DS.belongsTo 'campaign', { async: true }
  completion: DS.attr('number')

`export default CompletionPercentage`

with the corresponding DS.hasMany() association in the Location model. Right now I think maybe I don’t need it? Do I?

Essentially, I need to come up with sortable properties for these elements within the completion_percentages array and I just don’t know how to do it. What’s the right approach?

We’re using ember v2.0.0, ember-data v2.0.0, ember-cli v1.13.8.

Thanks in advance.