Skip to content

Instantly share code, notes, and snippets.

@amk221
Last active September 29, 2015 12:04
Show Gist options
  • Save amk221/7691aa55c2229df0dc7c to your computer and use it in GitHub Desktop.
Save amk221/7691aa55c2229df0dc7c to your computer and use it in GitHub Desktop.
Ember data duplicate records fix
import DS from 'ember-data';
export default DS.RESTAdapter;
import Ember from 'ember';
const equal = function(a, b, desc = '') {
return Ember.assert(desc, a === b);
}
export default Ember.Controller.extend({
appName:'Ember Data duplicate records fix',
isSaving: false,
actions: {
save() {
this.set('isSaving', true);
let store = this.get('store');
Ember.run(function() {
store.unloadAll('foo');
store.unloadAll('bar');
store.unloadAll('baz');
});
let foo = store.createRecord('foo', { name: 'foo 1' });
let bar1 = store.createRecord('bar', { name: 'bar 1' });
let bar2 = store.createRecord('bar', { name: 'bar 2' });
let baz1 = store.createRecord('baz', { name: 'baz 1' });
foo.get('bars').pushObject(bar1);
foo.get('bars').pushObject(bar2);
foo.set('baz', baz1);
equal(foo.get('name'), 'foo 1', 'foo model exists');
equal(foo.get('bars').objectAt(0).get('name'), 'bar 1', 'foo has many bars');
equal(foo.get('bars').objectAt(1).get('name'), 'bar 2', 'foo has many bars');
equal(foo.get('baz.name'), 'baz 1', 'foo has one baz');
equal(store.peekAll('bar').get('length'), 2, 'store knows about bars');
equal(store.peekAll('baz').get('length'), 1, 'store knows about baz');
foo.save().then(() => {
equal(foo.get('name'), 'foo 1 (saved)', 'foo model is updated');
equal(foo.get('bars').objectAt(0).get('name'), 'bar 1 (saved)', 'hasMany is updated');
equal(foo.get('bars').objectAt(1).get('name'), 'bar 2 (saved)', 'hasMany is updated');
equal(foo.get('baz.name'), 'baz 1 (saved)', 'belongsTo is updated');
equal(store.peekAll('bar').get('length'), 2, 'duplicate hasMany records are cleaned up');
equal(store.peekAll('baz').get('length'), 1, 'duplicate belongsTo records are cleaned up');
this.set('isSaving', false);
})
}
}
});
{{#if isSaving}}
Saving...
{{else}}
<button {{action 'save'}}>Save</button>
{{/if}}
This twiddle demonstrates a fix for this issue:
"Ember Data creates duplicate records"
https://github.com/emberjs/data/issues/1829
See models/foo.js #save for the fix
See application/controller.js #save for the tests
View the console for a list of hasMany and belongsTo records that are cleaned up.
import DS from 'ember-data';
export default DS.Model.extend({
name: DS.attr('string')
});
import DS from 'ember-data';
export default DS.Model.extend({
name: DS.attr('string')
});
import DS from 'ember-data';
export default DS.Model.extend({
name: DS.attr('string'),
bars: DS.hasMany('bar', { async: false }),
baz: DS.belongsTo('baz', { async: false }),
save: function() {
let recordsToDelete = [];
let cleanup = function(record) {
if (record && record.get('isNew')) {
recordsToDelete.push(record);
}
};
this.eachRelationship((name, descriptor) => {
if (descriptor.options.async) { return; }
if (descriptor.kind === 'hasMany') {
this.get(name).forEach(cleanup);
} else if (descriptor.kind === 'belongsTo') {
cleanup(this.get(name))
};
});
let promise = this._super();
console.log('Cleaning up', JSON.stringify(recordsToDelete));
promise.then(() => {
recordsToDelete.forEach((record) => {
Ember.run(function() {
let relationships = record._internalModel._implicitRelationships;
Object.keys(relationships).forEach((name) => delete relationships[name]);
record.deleteRecord();
});
});
});
return promise;
}
});
import DS from 'ember-data';
export default DS.RESTSerializer;
import DS from 'ember-data';
jQuery.mockjax({
url: '/foos',
type: 'POST',
responseText: {
foo: {
id: 1,
name: 'foo 1 (saved)',
bars: [
{ id: 1, name: 'bar 1 (saved)' },
{ id: 2, name: 'bar 2 (saved)' }
],
baz: {
id: 1,
name: 'baz 1 (saved)'
}
}
}
});
export default DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, {
attrs: {
bars: {
embedded: 'always'
},
baz: {
embedded: 'always'
}
}
});
{
"version": "0.4.11",
"dependencies": {
"jquery": "https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.3/jquery.js",
"ember": "https://cdnjs.cloudflare.com/ajax/libs/ember.js/2.0.0/ember.debug.js",
"ember-data": "https://cdnjs.cloudflare.com/ajax/libs/ember-data.js/2.0.0-beta.2/ember-data.js",
"ember-template-compiler": "https://cdnjs.cloudflare.com/ajax/libs/ember.js/2.0.0/ember-template-compiler.js",
"jquery-mockjax": "https://cdnjs.cloudflare.com/ajax/libs/jquery-mockjax/1.6.2/jquery.mockjax.js"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment