2

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!

James_1x0
  • 931
  • 10
  • 20
  • 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 Jul 31 '14 at 21:51
  • @Altrim: For ex. http://stackoverflow.com/questions/14521182/ember-data-does-not-support-embedded-objects - 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 Jul 31 '14 at 21:55
  • Are you using ember-data canary? If you check this commit https://github.com/emberjs/data/commit/67fed4b1c88a55f984218b638c3fafa5b5943be9 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 Jul 31 '14 at 21:59
  • 1
    Altrim: Upgrading to ember data canary worked with the EmbeddedRecordsMixin. Thanks so much. – James_1x0 Jul 31 '14 at 23:00

2 Answers2

1
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:

Brenden
  • 7,708
  • 11
  • 61
  • 75
-1

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

Community
  • 1
  • 1
Evolve
  • 8,939
  • 12
  • 51
  • 63
  • Nah, DS.EmbeddedRecordsMixin is a lot better than creating an async relationship. Less latency, and overall payload size and transfer time. – James_1x0 Oct 29 '14 at 17:13
  • Im not as confident on that part, does the rest of my advice make sense and would still work if I was to use embeded: load rather than async: true? I was more wanting to illustrate how the json looked and included the async as that worked for me. Happy to update my solution if so. – Evolve Oct 30 '14 at 01:38
  • http://emberjs.com/api/data/classes/DS.EmbeddedRecordsMixin.html#toc_using-embedded-records – James_1x0 Oct 30 '14 at 05:55