Last active
November 17, 2015 14:10
-
-
Save amk221/0dfc8aa40f2d95abdc96 to your computer and use it in GitHub Desktop.
Fix for Ember Data creating duplicate records
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { test, moduleForModel } from 'ember-qunit'; | |
import Model from 'ember-data/model'; | |
import BaseModel from 'capsule/pods/base/model'; | |
import attr from 'ember-data/attr'; | |
import run from 'ember-runloop'; | |
import DS from 'ember-data'; | |
import Pretender from 'pretender'; | |
import RESTSerializer from 'ember-data/serializers/rest'; | |
import { hasMany, belongsTo } from 'ember-data/relationships'; | |
moduleForModel('base'); | |
test('#save (fix for duplicate embedded records)', function(assert) { | |
assert.expect(12); | |
let foo, bar1, bar2, baz1; | |
let store = this.store(); | |
let payload = { | |
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)' | |
} | |
} | |
}; | |
let server = new Pretender(function() { | |
this.post('/foos', () => [200, {}, payload]); | |
}); | |
let FooSerializer = RESTSerializer.extend(DS.EmbeddedRecordsMixin, { | |
attrs: { | |
bars: { | |
embedded: 'always' | |
}, | |
baz: { | |
embedded: 'always' | |
} | |
} | |
}); | |
this.registry.register('serializer:foo', FooSerializer); | |
this.registry.register('serializer:bar', RESTSerializer); | |
this.registry.register('serializer:baz', RESTSerializer); | |
this.registry.register('model:bar', Model.extend({ name: attr('string') })); | |
this.registry.register('model:baz', Model.extend({ name: attr('string') })); | |
this.registry.register('model:foo', BaseModel.extend({ | |
name: attr('string'), | |
bars: hasMany('bar', { async: false }), | |
baz: belongsTo('baz', { async: false }) | |
})); | |
run(function() { | |
foo = store.createRecord('foo', { name: 'foo 1' }); | |
bar1 = store.createRecord('bar', { name: 'bar 1' }); | |
bar2 = store.createRecord('bar', { name: 'bar 2' }); | |
baz1 = store.createRecord('baz', { name: 'baz 1' }); | |
foo.get('bars').pushObject(bar1); | |
foo.get('bars').pushObject(bar2); | |
foo.set('baz', baz1); | |
}); | |
run(function() { | |
assert.equal(foo.get('name'), 'foo 1'); | |
assert.equal(foo.get('bars').objectAt(0).get('name'), 'bar 1'); | |
assert.equal(foo.get('bars').objectAt(1).get('name'), 'bar 2'); | |
assert.equal(foo.get('baz.name'), 'baz 1'); | |
assert.equal(store.peekAll('bar').get('length'), 2); | |
assert.equal(store.peekAll('baz').get('length'), 1); | |
foo.save().then(function() { | |
assert.equal(foo.get('name'), 'foo 1 (saved)'); | |
assert.equal(foo.get('bars').objectAt(0).get('name'), 'bar 1 (saved)'); | |
assert.equal(foo.get('bars').objectAt(1).get('name'), 'bar 2 (saved)'); | |
assert.equal(foo.get('baz.name'), 'baz 1 (saved)'); | |
assert.equal(store.peekAll('bar').get('length'), 2); | |
assert.equal(store.peekAll('baz').get('length'), 1); | |
}); | |
}); | |
server.shutdown(); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Model from 'ember-data/model'; | |
import run from 'ember-runloop'; | |
const { keys } = Object; | |
export default Model.extend({ | |
save(...args) { | |
let dupeRecords = []; | |
let addDupe = (record) => { | |
if (record && record.get('isNew')) { | |
dupeRecords.push(record); | |
} | |
}; | |
let implicitFix = (record) => { | |
let rels = record._internalModel._implicitRelationships; | |
keys(rels).forEach(name => delete rels[name]); | |
}; | |
let deleteDupe = (record) => { | |
run(() => { | |
implicitFix(record); | |
record.deleteRecord(); | |
}); | |
}; | |
this.eachRelationship((name, descriptor) => { | |
if (descriptor.options.async) { | |
return; | |
} | |
if (descriptor.kind === 'hasMany') { | |
this.get(name).forEach(addDupe); | |
} else if (descriptor.kind === 'belongsTo') { | |
addDupe(this.get(name)); | |
} | |
}); | |
return this._super(...args).then(() => { | |
dupeRecords.forEach(deleteDupe); | |
}); | |
} | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment