From 43b613683f48c6ac574c9a48e260ce36933e08fe Mon Sep 17 00:00:00 2001 From: Jonathan Johnson Date: Wed, 23 Aug 2017 13:06:48 -0700 Subject: [PATCH] [BUGFIX release] Load many2many relationships correctly When a many2many relationship exists and more than one related item is included in the relationship ensure that both sides load completely. This issue was introduced in e430edee24591afa562167c6f5775b61d1031b75 --- .../system/relationships/state/has-many.js | 5 +- .../unit/model/relationships/has-many-test.js | 130 ++++++++++++++++++ 2 files changed, 131 insertions(+), 4 deletions(-) diff --git a/addon/-private/system/relationships/state/has-many.js b/addon/-private/system/relationships/state/has-many.js index 55c89af15c3..d4685bec2f5 100644 --- a/addon/-private/system/relationships/state/has-many.js +++ b/addon/-private/system/relationships/state/has-many.js @@ -205,21 +205,18 @@ export default class ManyRelationship extends Relationship { return; } - let forCanonical = []; - for (let i = 0; i< internalModels.length; i++) { let internalModel = internalModels[i]; if (this.canonicalMembers.has(internalModel)) { continue; } - forCanonical.push(internalModel); this.canonicalMembers.add(internalModel); this.members.add(internalModel); this.setupInverseRelationship(internalModel); } - this.canonicalState.splice(0, this.canonicalState.length, ...forCanonical); + this.canonicalState = this.canonicalMembers.toArray(); } fetchLink() { diff --git a/tests/unit/model/relationships/has-many-test.js b/tests/unit/model/relationships/has-many-test.js index ff6612c3607..11cea3a24d5 100644 --- a/tests/unit/model/relationships/has-many-test.js +++ b/tests/unit/model/relationships/has-many-test.js @@ -465,6 +465,136 @@ test('hasMany with duplicates from payload', function(assert) { }); }); +test('many2many loads both sides #5140', function(assert) { + assert.expect(3); + + const Tag = DS.Model.extend({ + name: DS.attr('string'), + people: DS.hasMany('person', { async: false }) + }); + + Tag.reopenClass({ + toString() { + return 'tag'; + } + }); + + const Person = DS.Model.extend({ + name: DS.attr('string'), + tags: DS.hasMany('tags', { async: false }) + }); + + Person.reopenClass({ + toString() { + return 'person'; + } + }); + + let env = setupStore({ tag: Tag, person: Person }); + let { store } = env; + + run(() => { + // first we push in data with the relationship + store.push({ + data: [ + { + type: 'person', + id: 1, + attributes: { + name: 'David J. Hamilton' + }, + relationships: { + tags: [{ + data: { + type: 'tag', + id: 1 + } + }, + { + data: { + type: 'tag', + id: 2 + } + }] + } + }, + { + type: 'person', + id: 2, + attributes: { + name: 'Gerald Dempsey Posey' + }, + relationships: { + tags: [{ + data: { + type: 'tag', + id: 1 + } + }, + { + data: { + type: 'tag', + id: 2 + } + }] + } + }, + { + type: 'tag', + id: 1, + attributes: { + name: 'whatever' + }, + relationships: { + people: { + data: [ + { + type: 'person', + id: 1 + }, + { + type: 'person', + id: 2 + } + ] + } + } + }, + { + type: 'tag', + id: 2, + attributes: { + name: 'nothing' + }, + relationships: { + people: { + data: [ + { + type: 'person', + id: 1 + }, + { + type: 'person', + id: 2 + } + ] + } + } + } + ] + }); + }); + + run(() => { + let tag = store.peekRecord('tag', 1); + assert.equal(tag.get('people.length'), 2, 'relationship does contain all data'); + let person1 = store.peekRecord('person', 1); + assert.equal(person1.get('tags.length'), 2, 'relationship does contain all data'); + let person2 = store.peekRecord('person', 2); + assert.equal(person2.get('tags.length'), 2, 'relationship does contain all data'); + }); +}); + test('hasMany with explicit null works even when the inverse was set to not null', function(assert) { assert.expect(3);