4
votes

I'm trying to update a hasMany relation in Ember but I'm having a bit of trouble getting the data to send correctly.

I have the following Ember models:

// models/post.js
export default DS.Model.extend({
    title: DS.attr('string'),
    tags: DS.hasMany('tag', { async: true })
});

// models/tag.js
export default DS.Model.extend({
    title: DS.attr('string'),
    post: DS.belongsTo('post', { async: true })
});

And then I have the following action in my route to create a new tag and update the post:

addTag: function() {
    var post = this.get('currentModel');

    var newTag = this.store.createRecord('tag', {
        title: 'Lorem Ipsum',
        post: post
    });

    newTag.save().then(function() {
        post.get('tags').pushObject(newTag);

        post.save();
    });
}

The new tag is created successfully and saved by my Express api but the post doesn't get saved correctly. It's received by the api but the request payload made by Ember never contains the tag IDs (it does send the tag title though). What am I doing wrong? Would really appreciate any help!


Edit

It turns out the RESTSerializer by default doesn't serialize and include the related IDs for a hasMany relationship. It only includes them for the belongsTo side as it expects the API to take care of saving it where needed. I will probably change my API to fit this behaviour as it's more efficient but in case any one else comes across this, it is possible to make the serializer include the IDs by extending the serializer and using the DS.EmbeddedRecordsMixin mixin - http://emberjs.com/api/data/classes/DS.EmbeddedRecordsMixin.html - Which would look something like this:

export default DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, {
    attrs: {
        tags: { serialize: 'ids' }
    }
});
2

2 Answers

0
votes

You don't need to call .save() on post. When you call createRecord to create a tag, your backend receives id of post and should persist dependencies accordingly.

addTag: function() {
    var post = this.get('currentModel');

    this.store.createRecord('tag', {
          title: 'Lorem Ipsum',
          post: post})
       .save()
       .then(function(tag) {
          post.get('tags').pushObject(tag);
       });
0
votes

Meet the same problem.

Currently I solve it by serializeHasMany hook.

// app/serializers/application
import {ActiveModelSerializer} from 'active-model-adapter';

export default ActiveModelSerializer.extend({
  serializeHasMany: function(snapshot, json, relationship){
    this._super.apply this, arguments
    if (!json[relationship.type + '_ids']){
      var ids = []
      snapshot.record.get(relationship.key).forEach(function(item){
        ids.push item.get 'id'
      });
      json[relationship.type + '_ids'] = ids
    }
  }
})