Ember Data fixture adapter saving record loses has many relationships

I am having issues working with the Ember Data fixture adapter. When saving a record, all it’s hasMany relationships are lost.

My models and fixtures look like:

App.User = DS.Model.extend({
  name: DS.attr('string'),
  projects: DS.hasMany('project', { async: true})
});

App.Project = DS.Model.extend({
  name: DS.attr('string'),
  user: DS.belongsTo('user')
});

App.User.FIXTURES = [
  { id: 1, name: 'Kris', projects: [1,2] },
  { id: 2, name: 'Luke', projects: [1,2] }
];

App.Project.FIXTURES = [
  { id: 1, name: 'Ember' },
  { id: 2, name: 'Angular' }
];

And I am saving the record using:

App.UsersRoute = Ember.Route.extend({
  actions: {
    save: function(model) {
      var self = this;
      model.save().then(function() {
        this.transitionTo('users');
      });
    }
  },
  model: function(){ 
    return this.store.find('user');
  }
});

I have create a JS Bin to illustrate the issue and also posted on Stackoverflow.

Thanks

2 Likes

Seems like DS.JSONSerializer.serializeHasMany ignores manyToOne when serializing. I am getting around this by creating a custom serializer for the model and overwritting serializeHasMany so that it handles manyToOne relationship types.

var get = Ember.get;
App.UserSerializer = DS.RESTSerializer.extend({
  serializeHasMany: function(record, json, relationship) {
    var key = relationship.key;

    var relationshipType = DS.RelationshipChange.determineRelationshipType(record.constructor, relationship);

    if (relationshipType === 'manyToNone' || relationshipType === 'manyToMany' || relationshipType === 'manyToOne') {
      json[key] = get(record, key).mapBy('id');
      // TODO support for polymorphic manyToNone and manyToMany relationships
    }
  }
});
1 Like

I hit the same problem and came to the same solution. Surely this is a bug in ember-data?

Here’s my solution, the only difference is that I’m modifying JSONSerializer, rather than extended RESTSerializer because I’m using the local storage adapter.:

DS.JSONSerializer.reopen({
    serializeHasMany : function(record, json, relationship) {
        var key = relationship.key;

        var relationshipType = DS.RelationshipChange.determineRelationshipType(
                record.constructor, relationship);

        if (relationshipType === 'manyToNone'
                || relationshipType === 'manyToMany'
                || relationshipType === 'manyToOne') {
            json[key] = Ember.get(record, key).mapBy('id');
            // TODO support for polymorphic manyToNone and manyToMany
            // relationships
        }
    }
});

I ran into this issue as well. I didn’t realize until I found this question that other people have fixed the issue, but it still seems to be a problem on ember/data master. I fixed it by updating my local copy of emaber-data-1.0.0.beta-3.js directly. Seems like we should create an issue in the ember/data Github repo.

Also, I saw this using the local-storage-adapter, so it’s not exclusive to the fixture adapter.

Same issue here as well. I am also using fixture adapter.

Your solution fixed the problem. Is this really a bug? Or there is something wrong with our code?

@billcchkk could you open a PR against emberjs/data? I’m facing this same problem here while writing my tests.

@jefkoslowski My App.Cart hasMany App.Items. After .createRecord() is called, cart.get('items.length') is 1, but as soon as I call cart.save(), cart.get('items.length') returns 0. It’s definitely a bug in Ember Data.

Thanks.

Guys, I opened this PR with a failing spec, https://github.com/emberjs/data/pull/1606

If you guys think it makes sense, could you chime in?

I’ve just started out using the Fixture adapter, and ran into this. However, perhaps there are two separate issues here? The back-end I’ll be using will create a reciprocal “hasMany” for a “belongsTo” – so I have no need to write back the hasMany via REST: perhaps this should be configurable?

On the other hand, the Fixture adapter should clearly not loose hasMany on save – that is clearly a bug. Indeed from my POV the fixture adapter should automatically sync hasMany from related belongsTo… Any thoughts on this?

I also created a PR, https://github.com/emberjs/data/pull/1751 which adds the check for manyToOne