4
votes

I have a ember cli project and I am trying to replicate a simple scenario in which I have a Post model which hasMany Comment model. This relationship is polymorphic. I have two type Body Comment and Title Comment.

// app/models/post.js
import DS from 'ember-data';

export default DS.Model.extend({
    entry:          DS.attr('string'),
    comments:       DS.hasMany('comment', {polymorphic: true})
});


// app/models/comment.js
import DS from 'ember-data';

export default DS.Model.extend({
    text: DS.attr('string'),
    post: DS.belongsTo('post')
});

// app/models/body.js
import DS from 'ember-data';
import Comment from './comment';

export default Comment.extend({
    body: DS.attr('string')
});

// app/models/title.js
import DS from 'ember-data';
import Comment from './comment';

export default Comment.extend({
    title: DS.attr('string')
});

I have a serializer for Post model

import DS from 'ember-data';
export default DS.ActiveModelSerializer.extend(DS.EmbeddedRecordsMixin, {
  attrs: {
    comments: {
      embedded: 'always'
    }
  }
});

JSON returned by the server on GET /posts/1 is

{
    "posts": {
        "id": "1",
        "entry": "This is first post",
        "comments": [
            {
                "id": "1",
                "post": "1",
                "type": "body",
                "text": "This is the first comment on first post",
                "body": "This is a body comment"
            },
            {
                "id": "2",
                "post": "1",
                "type": "title",
                "text": "This is the second comment on first post",
                "title": "This is a title comment"
            }
        ]
    }
}

But Ember data is failing in deserializing the comments with the following error:

Error while processing route: index Cannot read property 'typeKey' of undefined TypeError: Cannot read property 'typeKey' of undefined
    at Ember.Object.extend.modelFor (http://localhost:4200/assets/vendor.js:71619:22)
    at Ember.Object.extend.recordForId (http://localhost:4200/assets/vendor.js:71074:25)
    at deserializeRecordId (http://localhost:4200/assets/vendor.js:72099:27)
    at deserializeRecordIds (http://localhost:4200/assets/vendor.js:72116:9)
    at http://localhost:4200/assets/vendor.js:72081:11
    at http://localhost:4200/assets/vendor.js:70135:20
    at http://localhost:4200/assets/vendor.js:17687:20
    at Object.OrderedSet.forEach (http://localhost:4200/assets/vendor.js:17530:14)
    at Object.Map.forEach (http://localhost:4200/assets/vendor.js:17685:14)
    at Function.Model.reopenClass.eachRelationship (http://localhost:4200/assets/vendor.js:70134:42) 

This happens when the following code is executed:

import Ember from 'ember';

export default Ember.Route.extend({
    model: function() {
        return this.store.find('post', 1);
    },

    setupController: function(controller, model) {
        console.log("Post entry: " + model.get('entry'));
        var comments = model.get('comments');
        comments.forEach(function(comment){
            console.log("Comment: " + comment.get('text'));
            console.log(typeof comment);
            //console.log("Comment Body " + comment.get('body'));
            //console.log("Comment Title " + comment.get('title'));
        });
    }
});

Please help me in understanding if I am doing something wrong and if yes then what is the correct way to solve a requirement like this.

1

1 Answers

2
votes

So @Dipayan you aren't necessarily doing anything wrong here, Ember Data just doesn't yet support HasMany Embedded Polymorphic relationships yet. Polymorphic embedded hasMany relationship. It will give the TypeError: Cannot read property 'typeKey' of undefined if you try to use it, which is precisely what you're getting.

If you have control of how your server handles the data you can keep the polymorphic, but lose the embedded, and instead use side-loading. For an example and good explanation of using polymorphic in this way check out Topal's Guide to Ember Data.