2
votes

Trying to load a plan model, embedded, into my app model.

I keep getting the following error when loading (it saves just fine):

Cannot read property 'typeKey' of undefined TypeError: Cannot read property 'typeKey' of undefined
at Ember.Object.extend.modelFor (http://localhost:4200/assets/vendor.js:71051:22)
at Ember.Object.extend.recordForId (http://localhost:4200/assets/vendor.js:70496:21)
at deserializeRecordId (http://localhost:4200/assets/vendor.js:71500:27)
at http://localhost:4200/assets/vendor.js:71477:11
at http://localhost:4200/assets/vendor.js:69701: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:69700:42)
at normalizeRelationships (http://localhost:4200/assets/vendor.js:71463:12) vendor.js:17062logToConsole

With that said I have the following models,

app/models/app.js

export default DS.Model.extend({
  name:    attribute('string'),
  domain:  attribute('string'),
  plan:    DS.belongsTo('plan', { embedded: 'load' }),
  creator: DS.belongsTo('user', { async: true }),

  time_stamp: attribute('string', {
    defaultValue: function () {
       return moment().format("YYYY/MM/DD HH:mm:ss");
    }
  })
});

app/models/plan.js

export default DS.Model.extend({
  price:       attribute('number'),
  description: attribute('string'),
  tagline:     attribute('string'),
  title:       attribute('string'),
  features:    attribute('array') // Array is defined in a transform, don't worry.
});

Plan being kind of a static document.

Here's my server response when calling store.get('creator.apps');

{
  "apps":[
    {
      "_id":"53da9994b2878d0000a2e68f",
      "name":"Myapp",
      "domain":"http://myapp.com",
      "creator":"53d9598bb25244e9b1a72e53",
      "plan":{
        "_id":"53d93c44b760612f9d07c921",
        "price":0,
        "description":"Free plan",
        "tagline":"Great for testing",
        "title":"Developer",
        "features":["5,000 Requests","API/Plugin Access"],
        "__v":0
      },
      "time_stamp":"2014/07/31 13:31:32",
      "__v":0
    }
  ]
}

I realize that the typeKey error is due to Ember not finding a model for the response. I can confirm that it finds the app type, firing a hook under normalizeHash.apps.

Sorry this is such a long post, just can't wrap my head around the cause of the issue!

2
Sorry but what is { embedded: 'load' } I've never seen in ember-data that? The recently fixed some issues in ember-data concerning embedded . If you run canary build of ember-data you can create a serializer for your model and include DS.EmbeddedRecordsMixin then you specify in attrs hash the embedded attribute attrs: {plan: {embedded: 'always'}}. Hope this helps - Altrim
@Altrim: For ex. stackoverflow.com/questions/14521182/… - But I did try that as well. ended up with: TypeError: undefined is not a function at Ember.Mixin.create.extractArray (http://localhost:4200/assets/vendor.js:61286:25). - James_1x0
Are you using ember-data canary? If you check this commit github.com/emberjs/data/commit/… they added Support for using EmbeddedRecordsMixin with JSONSerializer. I am using the mixin with embedded data and it works fine. I got the same error as you prior to using the canary build. - Altrim
Altrim: Upgrading to ember data canary worked with the EmbeddedRecordsMixin. Thanks so much. - James_1x0

2 Answers

1
votes
App.Thing = DS.Model.extend(
    {
        name: attr('string'),
        children: DS.hasMany('child', {inverse:null})
    }
);

App.ThingSerializer = DS.RESTSerializer.extend(
    DS.EmbeddedRecordsMixin, {
        attrs: {
            children: { embedded: 'always' }
        }
    }
);

DS.EmbeddedRecordsMixin must be in your model and you must have `embedded:'always' for the correct attribute.

If you have a Thing model then you can make Ember Data load the embedded children (here and array of nested objects) by using the model specific serializer.

Resources:

-1
votes

Ember doesn't want to have the record embedded in the JSON of the parent record. Do what you need to, to get your json like this. With just the plan id.

{
  "apps":[
    {
      "_id":"53da9994b2878d0000a2e68f",
      "name":"Myapp",
      "domain":"http://myapp.com",
      "creator":"53d9598bb25244e9b1a72e53",
      "plan_id":"53d93c44b760612f9d07c921",    // just output id only not embedded record 
      "time_stamp":"2014/07/31 13:31:32",
      "__v":0
    }
  ]
}

This then lets ember look up the related model itself, using the async: true

export default DS.Model.extend({
  name:    attribute('string'),
  domain:  attribute('string'),
  plan:    DS.belongsTo('plan', { async: true }),     //changed
  creator: DS.belongsTo('user', { async: true }),

  time_stamp: attribute('string', {
    defaultValue: function () {
       return moment().format("YYYY/MM/DD HH:mm:ss");
    }
  })

});

I've just gone through the pain of this myself and with some help found an answer.

For anyone else who's come here and still is has issues, read my answer to my own question for a detailed rundown of what the typeKey error means and further steps I used to resolve the issue myself.

Deploying ember-rails to Heroku - TypeError: Cannot read property 'typeKey' of undefined