Trying to make findAll return multiple type of models


#1

In a route’s model hook, I send a request to the server for all Journal models:

this.store.findAll('journal');

Thing is, Journal is actually just an abstract class for anything “journal”. For example, I have a Report and a Measurement model both extending from Journal. The server reponse (using REST) returns something like this:

{
  "Journals": [
    { "id": "report_1", "type":"Report", ... },
    { "id": "measurement_1", "type":"Measurement", ... }
  ]
}

What I try to accomplish: a) Make sure they are normalized to the right models; b) Make sure findAll returns an array containing all these different types of records.

The first step is no problem. There are several hooks in either an adapter (handleResponse) or a serializer (normalize, normalizeFindAllResponse) to achieve this. Using the Ember Inspector I can see I have a Report and Measurement record pushed to the store instead of two Journal records.

The second step is currently giving me a headache though. Whatever I try, the findAll always returns an empty array. Whatever hook I use to normalize to the right model, these models are somehow excluded from the findAll reponse by the “magic” of Ember Data.

So I created a custom findAll method on the journal adapter which looks something like this:

findAll() {
  const url = this.buildURL('journal', null, null, 'findAll');
  return this.get('ajax').request(url).then(payload => {
    return payload.map(journal => {
      return this.get('store').push({
        data: {
          id: journal.id,
          type: journal.type,
          attributes: journal
        }
      });
    });
  });
}

Once again, the right records are pushed to the store, but once again, the route’s model hook receives an empty array. And once again, I’m wondering what Ember Data is doing “behind the scenes” to prevent me from returning an array containing all records. Additionally this also creates the next warnings:

WARNING: Encountered "0" in payload, but no model was found for model name "0" (resolved model name using care-home@serializer:journal:.modelNameFromPayloadKey("0"))
WARNING: Encountered "1" in payload, but no model was found for model name "1" (resolved model name using care-home@serializer:journal:.modelNameFromPayloadKey("1"))

Ofcourse I can ignore adapters/serializers and create a service with a method doing exactly what I want. But I’m trying to stick as close as possible to Ember Data since it’s a part of this project and this should be something I can accomplish using adapters/serializers.

Any help is greatly appreciated. Thanks. :slight_smile:


#2

Perhaps you can create a hash like this https://github.com/broerse/ember-cli-blog/blob/master/app/routes/posts.js#L6 and use setupController to set the models in this hash…


#3

Depending on your server configuration, Ember Data can handle polymorphic models just fine. For example, when using JSONAPI, I know that it works quite well.

Basically, you’d just make models that extend from the same base model, e.g.:

// app/models/journal.js
export default DS.Model.extend({
  // shared attributes go here
});
// app/models/report.js and app/models/measurement.js
import Journal from './journal';
export default Journal.extend({
});

You should then be able to do store.findAll('journal') as well as store.findAll('measurement'), which will fetch from the API at /journals or /measurements respectively (depending on your adapter). This requires that the API response contains the model type, which seems to be the case in your example. So when fetching from /journals it can contain both measurements as well as reports.

A model can then even have a mixed relationship, e.g. journals: DS.hasMany('journal')