2

I have two models like this:

App.Build = DS.Model.extend({
    allegiance: DS.attr('string'),
    profession: DS.attr('string'),
        skills: DS.hasMany('skill')
});

App.Skill = DS.Model.extend({
    name:DS.attr('string'),
    value:DS.attr('number')
});

In my app, I have controls to set the allegiance, profession, and values of each skill (there's up to 55).

Then in the actions hash of my application controller, I have an action to save the build model to the server.

save:function(){
     var store = this.get('store');
     var skills = this.get('controllers.skills').get('model');
     console.log(skills);
     var build = store.createRecord('build',{
          profession:1,
          allegiance:1,
          skills:skills
      });

      build.set('skills',skills);
      build.save();

      console.log('Saved!');
}

But when the build model is sent to the server the skills property is an empty array:

{"build":{"allegiance":"1","profession":"1","skills":[]}}

I'm sure I'm doing something wrong, but I can't figure out what and can't find any good documentation about it. An additional note, all I care about submitting is the skill id and value.

Any help will be greatly appreciated!

UPDATE:

Following Daniel's suggestion, I've edited the save function to use pushObjects to put the skills into the Build model, then save it. It's working better now. The generated post data is like this now:

{"build":{
    "allegiance":1,
     "profession":1,
          "skills":["1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20","21","22","23","24","25","26","27","28","29","30","31","32","33","34","35","36","37","38","39","40","41","42","43","44","45","46","47","48","49","50","51","52","53","54","55"]}}

That being a list of the skill ids. None of the other attributes are submitted in the post. I've tried iterating over skills, creating a new object, and just pushing in the id and value, which are the only parts I need, but that gives me an error. Something like, can not use undefined, must be type skill.

This seems like something Ember data should handle natively. Is there something I'm missing to get it to send the other skill attributes in the request?

Thanks!!

NicholasJohn16
  • 2,390
  • 2
  • 21
  • 45

2 Answers2

6

If anyone else is interested, I solved the issue by overriding the serlizer with a custom serliazer for the Build model like this:

App.BuildSerializer = DS.RESTSerializer.extend({
     serializeHasMany: function(record, json, relationship) {
         if(relationship.key === 'skills') {
            var skills = record.get('skills');
            var block = [];

            skills.forEach(function(skill, index) {
                var current = {};
                current.id = skill.get('id');
                current.value = skill.get('value')
                block[index] = current;
            });

            json['skills'] = block;

         } else {
             return this._super(record,json,relationship);
         }
     }
});

UPDATE:

There's a much easier way to do this now using the DS.EmbeddedRecordsMixin like this:

App.BuildSerializer = DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin,{
    attrs: {
        skills: 'records'
    }
});
NicholasJohn16
  • 2,390
  • 2
  • 21
  • 45
  • 1
    There's a much better way to do this now. Using the [DS.EmbeddedRecordsMixin](http://emberjs.com/api/data/classes/DS.EmbeddedRecordsMixin.html) you can add associated records in with just a few lines of code. – NicholasJohn16 Dec 30 '14 at 18:12
0

Is the skills model a RecordArray? That's the underlying model Ember data uses. You might try creating the record then using pushObjects after the fact.

  var build = store.createRecord('build',{
      profession:1,
      allegiance:1
  });

  build.get('skills').pushObjects(skills);

additionally, save returns a promise, so in order to properly handle the successful save versus failure you can handle it like this.

 build.save().then(
    function(){
     console.log('Saved!');
    },
    function(){
     console.log('Failed to save');
    });
Kingpin2k
  • 47,277
  • 10
  • 78
  • 96
  • Nope, that doesn't seem to work. I get an error. I think skills is a `PromiseArray`. It's loaded from `/skills`. – NicholasJohn16 Oct 18 '13 at 20:49
  • can you iterate over skills? skills.forEach(function(sk){console.log(sk);}); – Kingpin2k Oct 18 '13 at 20:53
  • Yes, I should be able to iterate over it. I'm just not sure what to do with it at that point. This is the error I get when try pushObjects: Uncaught Error: Attempted to handle event `didSetProperty` on while in state root.deleted.saved. Called with {name: allegiance, oldValue: undefined, originalValue: undefined, value: undefined}. – NicholasJohn16 Oct 18 '13 at 22:16
  • is skllls null/undefined? console.log(build.get('skills')) – Kingpin2k Oct 19 '13 at 00:11
  • No, it isn't null/undefined. It's a PromiseArray. – NicholasJohn16 Oct 19 '13 at 00:17
  • Sorry, I meant the skills property on the build record. – Kingpin2k Oct 19 '13 at 03:12
  • Actually, that error was something completely unrelated and I resolved it. I attempted your suggestion again and got the following error now: Assertion failed: You cannot add 'undefined' records to this relationship (only 'skill' allowed) I'm a bit lost as to why it would be undefined. When I console.log skills, it is defined and I can even find the skills in the content property. Thank you for all your help so far! If you have any other ideas, it's appreciated! – NicholasJohn16 Oct 19 '13 at 08:49
  • Eureka! I had pushObject instead of pushObjects by mistake. I fixed it an it's now including the list of skill ids in with the build post, but it's not including any of the values? – NicholasJohn16 Oct 19 '13 at 09:57
  • Where is it not including any values? The POST? On the Ember Object? You can always try addObjects, or iterating through each object (test/output to see that the object isn't just an id, but is a skill object) and pushing them one at a time with pushObject/addObject. – Kingpin2k Oct 19 '13 at 15:27
  • Sorry for not being clear. It's including all the skill ids in the build post, but it's not including any of the other properties like name or value. I thought it would include a subobject with all the skill properties in it. Is there a way to get it to do that? – NicholasJohn16 Oct 19 '13 at 23:16
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/39588/discussion-between-nicholasjohn16-and-daniel) – NicholasJohn16 Oct 20 '13 at 09:41