kurko / ember-indexeddb-adapter

Ember Data IndexedDB Adapter
MIT License
43 stars 16 forks source link

hasMany relationships disappear on .save() and when the page is reloaded #9

Closed fieldscage closed 10 years ago

fieldscage commented 10 years ago

One to one relationships work perfectly but I'm having issues with the hasMany relationships.

I have a team that hasMany teamMembers. When I create the team I can view all the teamMembers by looping through them in my view. However when I refresh the page no teamMembers are shown. When I look in my indexedDB I see the team object with an array of teamMebmer ids. It's in the database but I don't think ember is reading it properly.

Here is the second scenario. A team can haveMany workspaces also. I create the workspace successfully and see it in my view when I loop through workspaces of a team.

var workspaceModel =  this.store.createRecord('workspace', {
    color: '95A5A6',
    team: teamModel
});

The moment I call workspaceModel.save() the workspace disappears from the view.

On both of these if I try to find() them I get the appropriate teamMembers or workspaces

teamMembers: function() {
    return this.store.find('teamMember', { team: this.get('model.id') });
}.property('model.id'),

workspaces: function() {
    return this.store.find('workspace', { team: this.get('model.id') })
}.property('model.id')

I've searched around with not much luck but heard a few people say that they had to override the implementation of "serializeHasMany" in JSONSerializer to get similar problems to work. Not sure if that has anything to do with this but I wanted to throw it out there.

kurko commented 10 years ago

Thanks a lot for this, @fieldscage. I had similar problems in other adapters as well. AFAIK, this is a bug in Ember Data itself. They're working in something they call single-source-of-truth which promises to address all these inconsistencies.

What I do to get rid of such problems is:

1) save the parent without associating the child, 2) in the parent's .save().then(function(parent) {} ) function, do

child = this.store('child', {name: 'ha'});
parent.get('children').push(child);
child.save();

It's weird, but does the trick. Could you try it?

fieldscage commented 10 years ago

Thank you for the quick reply! I'm new to Ember so I might be doing something incorrect. When i call .push() I get the error TypeError: undefined is not a function

If you can please help me understand what I'm doing wrong. This is what my original code looked like:

WBApp.Team = DS.Model.extend({
    name: DS.attr('string'),
    teamMembers: DS.hasMany('teamMember')
});

WBApp.TeamMember = DS.Model.extend({
    team: DS.belongsTo('team'),
    account: DS.belongsTo('account'),
    isAdmin: DS.attr('boolean')
});

WBApp.Account = DS.Model.extend({
    firstName: DS.attr('string'),
    lastName: DS.attr('string'),
    fullName: function() {
        return '%@ %@'.fmt(this.get('firstName'), this.get('lastName'))
    }.property('firstName', 'lastName'),
});

var team1 = store.createRecord('team', {
    name: this.get('name')
});
team1.save();

var person1 = store.createRecord('account', {
    firstName: "Fields",
    lastName: "Cage"
});

var tm1 = store.createRecord('teamMember', {
    team: team1,
    account: person1,
    isAdmin: 1
});
tm1.save(); // team1's teamMembers is automatically populated with tm1's id

And (with the models staying the same) this is what my code should look like from your suggestion but is receiving an error at .push()

var team1 = store.createRecord('team', {
    name: this.get('name')
});

var person1 = store.createRecord('account', {
    firstName: "Fields",
    lastName: "Cage"
});

var tm1 = store.createRecord('teamMember', {
    account: person1,
    isAdmin: 1
});

team1.save().then(
    function(team) {
        team.get('teamMembers').push(tm1);
        tm1.save()
    }
);