Skip to content

Commit a37309a

Browse files
authoredApr 23, 2021
chore: convert relationships to use identifiers (emberjs#7470)
* graph * fix rebase and address comments * fixup
1 parent 3d07414 commit a37309a

37 files changed

+1238
-716
lines changed
 

‎.prettierrc

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
singleQuote: true
22
trailingComma: 'es5'
3-
printWidth: 120
3+
printWidth: 120

‎packages/-ember-data/tests/acceptance/relationships/belongs-to-test.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { setupRenderingTest } from 'ember-qunit';
1010
import { ServerError } from '@ember-data/adapter/error';
1111
import JSONAPIAdapter from '@ember-data/adapter/json-api';
1212
import Model, { attr, belongsTo, hasMany } from '@ember-data/model';
13+
import { implicitRelationshipsFor } from '@ember-data/record-data/-private';
1314
import JSONAPISerializer from '@ember-data/serializer/json-api';
1415
import Store from '@ember-data/store';
1516

@@ -259,7 +260,9 @@ module('async belongs-to rendering tests', function(hooks) {
259260
},
260261
});
261262

262-
const implicitRelationships = pete._internalModel.__recordData.__implicitRelationships;
263+
const storeWrapper = store._storeWrapper;
264+
const identifier = pete._internalModel.identifier;
265+
const implicitRelationships = implicitRelationshipsFor(storeWrapper, identifier);
263266
const implicitKeys = Object.keys(implicitRelationships);
264267
const petOwnerImplicit = implicitRelationships[implicitKeys[0]];
265268

‎packages/-ember-data/tests/integration/record-data/record-data-errors-test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ class TestRecordData implements RecordData {
102102
isAttrDirty(key: string) {
103103
return false;
104104
}
105-
removeFromInverseRelationships(isNew: boolean) {}
105+
removeFromInverseRelationships() {}
106106

107107
_initRecordCreateOptions(options) {
108108
return {};

‎packages/-ember-data/tests/integration/record-data/record-data-state-test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ class TestRecordData implements RecordData {
9999
isAttrDirty(key: string) {
100100
return false;
101101
}
102-
removeFromInverseRelationships(isNew: boolean) {}
102+
removeFromInverseRelationships() {}
103103

104104
_initRecordCreateOptions(options) {
105105
return {};

‎packages/-ember-data/tests/integration/record-data/record-data-test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ class TestRecordData {
7979
isAttrDirty(key: string) {
8080
return false;
8181
}
82-
removeFromInverseRelationships(isNew: boolean) {}
82+
removeFromInverseRelationships() {}
8383

8484
_initRecordCreateOptions(options) {}
8585
isNew() {

‎packages/-ember-data/tests/integration/record-data/store-wrapper-test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ class TestRecordData {
7979
isAttrDirty(key: string) {
8080
return false;
8181
}
82-
removeFromInverseRelationships(isNew: boolean) {}
82+
removeFromInverseRelationships() {}
8383

8484
_initRecordCreateOptions(options) {}
8585
}

‎packages/-ember-data/tests/integration/references/has-many-test.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ module('integration/references/has-many', function(hooks) {
262262
},
263263
relationships: {
264264
family: {
265-
data: { type: 'family', id: '2' },
265+
data: { type: 'family', id: '1' },
266266
},
267267
},
268268
},

‎packages/-ember-data/tests/integration/relationships/belongs-to-test.js

+1-173
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,9 @@ import { setupTest } from 'ember-qunit';
1010

1111
import JSONAPIAdapter from '@ember-data/adapter/json-api';
1212
import Model from '@ember-data/model';
13-
import { RecordData, relationshipsFor, relationshipStateFor } from '@ember-data/record-data/-private';
13+
import { relationshipsFor, relationshipStateFor } from '@ember-data/record-data/-private';
1414
import JSONAPISerializer from '@ember-data/serializer/json-api';
1515
import Store from '@ember-data/store';
16-
import { identifierCacheFor, recordDataFor } from '@ember-data/store/-private';
1716
import testInDebug from '@ember-data/unpublished-test-infra/test-support/test-in-debug';
1817

1918
const { attr: DSattr, hasMany: DShasMany, belongsTo: DSbelongsTo } = DS;
@@ -2005,175 +2004,4 @@ module('integration/relationship/belongs_to Belongs-To Relationships', function(
20052004

20062005
assert.equal(count, 0);
20072006
});
2008-
2009-
test("belongsTo relationship doesn't trigger when model data doesn't support implicit relationship", function(assert) {
2010-
class TestRecordData extends RecordData {
2011-
constructor(...args) {
2012-
super(...args);
2013-
delete this.__implicitRelationships;
2014-
delete this.__relationships;
2015-
}
2016-
2017-
_destroyRelationships() {}
2018-
2019-
_allRelatedRecordDatas() {
2020-
return [this];
2021-
}
2022-
2023-
_cleanupOrphanedRecordDatas() {}
2024-
2025-
destroy() {
2026-
this.isDestroyed = true;
2027-
this.storeWrapper.disconnectRecord(this.modelName, this.id, this.clientId);
2028-
}
2029-
2030-
get _implicitRelationships() {
2031-
return undefined;
2032-
}
2033-
get _relationships() {
2034-
return undefined;
2035-
}
2036-
}
2037-
2038-
Chapter.reopen({
2039-
// book is still an inverse from prior to the reopen
2040-
sections: DS.hasMany('section', { async: false }),
2041-
book1: DS.belongsTo('book1', { async: false, inverse: 'chapters' }), // incorrect inverse
2042-
book2: DS.belongsTo('book1', { async: false, inverse: null }), // correct inverse
2043-
});
2044-
2045-
let store = this.owner.lookup('service:store');
2046-
2047-
const createRecordDataFor = store.createRecordDataFor;
2048-
store.createRecordDataFor = function(modelName, id, lid, storeWrapper) {
2049-
if (modelName === 'book1' || modelName === 'section') {
2050-
let identifier = identifierCacheFor(this).getOrCreateRecordIdentifier({
2051-
type: modelName,
2052-
id,
2053-
lid,
2054-
});
2055-
return new TestRecordData(identifier, storeWrapper);
2056-
}
2057-
return createRecordDataFor.call(this, modelName, id, lid, storeWrapper);
2058-
};
2059-
2060-
const data = {
2061-
data: {
2062-
type: 'chapter',
2063-
id: '1',
2064-
relationships: {
2065-
book1: {
2066-
data: { type: 'book1', id: '1' },
2067-
},
2068-
book2: {
2069-
data: { type: 'book1', id: '2' },
2070-
},
2071-
book: {
2072-
data: { type: 'book', id: '1' },
2073-
},
2074-
sections: {
2075-
data: [
2076-
{
2077-
type: 'section',
2078-
id: 1,
2079-
},
2080-
{
2081-
type: 'section',
2082-
id: 2,
2083-
},
2084-
],
2085-
},
2086-
},
2087-
},
2088-
included: [
2089-
{ type: 'book1', id: '1' },
2090-
{ type: 'book1', id: '2' },
2091-
{ type: 'section', id: '1' },
2092-
{ type: 'book', id: '1' },
2093-
{ type: 'section', id: '2' },
2094-
],
2095-
};
2096-
2097-
// Expect assertion failure as Book1 RecordData
2098-
// doesn't have relationship attribute
2099-
// and inverse is not set to null in
2100-
// DSbelongsTo
2101-
assert.expectAssertion(() => {
2102-
run(() => {
2103-
store.push(data);
2104-
});
2105-
}, `Assertion Failed: We found no inverse relationships by the name of 'chapters' on the 'book1' model. This is most likely due to a missing attribute on your model definition.`);
2106-
2107-
//Update setup
2108-
// with inverse set to null
2109-
// no errors thrown
2110-
Chapter.reopen({
2111-
book1: DS.belongsTo({ async: false }),
2112-
sections: DS.hasMany('section', { async: false }),
2113-
book: DS.belongsTo({ async: false, inverse: null }),
2114-
});
2115-
2116-
run(() => {
2117-
store.push(data);
2118-
});
2119-
2120-
let chapter = store.peekRecord('chapter', '1');
2121-
let book1 = store.peekRecord('book1', '1');
2122-
let book2 = store.peekRecord('book1', '2');
2123-
let book = store.peekRecord('book', '1');
2124-
let section1 = store.peekRecord('section', '1');
2125-
let section2 = store.peekRecord('section', '2');
2126-
2127-
let sections = chapter.get('sections');
2128-
2129-
assert.equal(chapter.get('book1.id'), '1');
2130-
assert.equal(chapter.get('book2.id'), '2');
2131-
assert.equal(chapter.get('book.id'), '1');
2132-
2133-
// No inverse setup created for book1
2134-
// as Model-Data of book1 doesn't support this
2135-
// functionality.
2136-
assert.notOk(book1.get('chapter'));
2137-
assert.notOk(book2.get('chapter'));
2138-
assert.notOk(book.get('chapter'));
2139-
assert.notOk(
2140-
recordDataFor(book1)._implicitRelationships,
2141-
'no support for implicit relationship in custom RecordData'
2142-
);
2143-
assert.notOk(
2144-
recordDataFor(book2)._implicitRelationships,
2145-
'no support for implicit relationship in custom RecordData'
2146-
);
2147-
assert.ok(recordDataFor(book)._implicitRelationships, 'support for implicit relationship in default RecordData');
2148-
2149-
// No inverse setup is created for section
2150-
assert.notOk(section1.get('chapter'));
2151-
assert.notOk(section2.get('chapter'));
2152-
2153-
// Removing the sections
2154-
// shouldnot throw error
2155-
// as Model-data of section
2156-
// doesn't support implicit Relationship
2157-
run(() => {
2158-
chapter.get('sections').removeObject(section1);
2159-
assert.notOk(recordDataFor(section1)._implicitRelationships);
2160-
2161-
chapter.get('sections').removeObject(section2);
2162-
assert.notOk(recordDataFor(section2)._implicitRelationships);
2163-
});
2164-
2165-
assert.equal(chapter.get('sections.length'), 0);
2166-
2167-
// Update the current state of chapter by
2168-
// adding new sections
2169-
// shouldnot throw error during
2170-
// setup of implicit inverse
2171-
run(() => {
2172-
sections.addObject(store.createRecord('section', { id: 3 }));
2173-
sections.addObject(store.createRecord('section', { id: 4 }));
2174-
sections.addObject(store.createRecord('section', { id: 5 }));
2175-
});
2176-
assert.equal(chapter.get('sections.length'), 3);
2177-
assert.notOk(recordDataFor(sections.get('firstObject'))._implicitRelationships);
2178-
});
21792007
});

‎packages/-ember-data/tests/integration/relationships/inverse-relationships-test.js

+8-10
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { module, test } from 'qunit';
55
import { setupTest } from 'ember-qunit';
66

77
import Model, { attr, belongsTo, hasMany } from '@ember-data/model';
8+
import { graphFor } from '@ember-data/record-data/-private';
89
import testInDebug from '@ember-data/unpublished-test-infra/test-support/test-in-debug';
910

1011
module('integration/relationships/inverse_relationships - Inverse Relationships', function(hooks) {
@@ -679,16 +680,13 @@ module('integration/relationships/inverse_relationships - Inverse Relationships'
679680

680681
await settled();
681682

682-
assert.deepEqual(
683-
comment._internalModel.__recordData.__relationships.initializedRelationships,
684-
{},
685-
'relationships are cleared'
686-
);
687-
assert.equal(
688-
comment._internalModel.__recordData.__implicitRelationships,
689-
null,
690-
'implicitRelationships are cleared'
691-
);
683+
const identifier = comment._internalModel.identifier;
684+
const relationships = graphFor(store._storeWrapper).get(identifier);
685+
const implicitRelationships = graphFor(store._storeWrapper).getImplicit(identifier);
686+
const initializedRelationships = relationships.initializedRelationships;
687+
688+
assert.deepEqual(Object.keys(initializedRelationships), [], 'relationships are cleared');
689+
assert.deepEqual(Object.keys(implicitRelationships), [], 'implicitRelationships are cleared');
692690
assert.ok(comment._internalModel.__recordData.isDestroyed, 'recordData is destroyed');
693691
});
694692
});
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,68 @@
1-
import { recordDataFor } from '@ember-data/store/-private';
1+
import { graphFor } from './graph/index';
22

3+
type RecordDataStoreWrapper = import('@ember-data/store/-private').RecordDataStoreWrapper;
4+
type StableRecordIdentifier = import('@ember-data/store/-private/ts-interfaces/identifier').StableRecordIdentifier;
5+
type InternalModel = import('@ember-data/store/-private').InternalModel;
36
type RelationshipRecordData = import('./ts-interfaces/relationship-record-data').RelationshipRecordData;
4-
type ConfidentDict<T> = import('@ember-data/store/-private/ts-interfaces/utils').ConfidentDict<T>;
7+
type RelationshipDict = import('@ember-data/store/-private/ts-interfaces/utils').ConfidentDict<Relationship>;
58
type ManyRelationship = import('./relationships/state/has-many').default;
69
type BelongsToRelationship = import('./relationships/state/belongs-to').default;
710
type Relationship = import('./relationships/state/relationship').default;
811
type Relationships = import('./relationships/state/create').default;
912

10-
export function relationshipsFor(instance: any): Relationships {
11-
let recordData = (recordDataFor(instance) || instance) as RelationshipRecordData;
13+
type MappableToRelationships = { _internalModel: InternalModel };
1214

13-
return recordData._relationships;
14-
}
15+
export function relationshipsFor(instance: RecordDataStoreWrapper, identifier: StableRecordIdentifier): Relationships;
16+
export function relationshipsFor(instance: MappableToRelationships): Relationships;
17+
export function relationshipsFor(
18+
instance: MappableToRelationships | RecordDataStoreWrapper,
19+
identifier?: StableRecordIdentifier
20+
): Relationships {
21+
if (!identifier) {
22+
let internalModel = ((instance as unknown) as MappableToRelationships)._internalModel;
23+
identifier = internalModel.identifier;
24+
25+
// safe to upgrade as relationshipsFor is a private util used only for our own things
26+
instance = (internalModel._recordData as RelationshipRecordData).storeWrapper;
27+
}
1528

16-
export function relationshipStateFor(instance: any, propertyName: string): BelongsToRelationship | ManyRelationship {
17-
return relationshipsFor(instance).get(propertyName);
29+
return graphFor(instance as RecordDataStoreWrapper).get(identifier);
1830
}
1931

20-
export function implicitRelationshipsFor(instance: any): ConfidentDict<Relationship> {
21-
let recordData = (recordDataFor(instance) || instance) as RelationshipRecordData;
32+
export function relationshipStateFor(
33+
instance: RecordDataStoreWrapper,
34+
identifier: StableRecordIdentifier,
35+
propertyName: string
36+
): BelongsToRelationship | ManyRelationship;
37+
export function relationshipStateFor(
38+
instance: MappableToRelationships,
39+
identifier: string
40+
): BelongsToRelationship | ManyRelationship;
41+
export function relationshipStateFor(
42+
instance: RecordDataStoreWrapper | MappableToRelationships,
43+
identifier: string | StableRecordIdentifier,
44+
propertyName?: string
45+
): BelongsToRelationship | ManyRelationship {
46+
if (!propertyName) {
47+
let internalModel = ((instance as unknown) as MappableToRelationships)._internalModel;
48+
propertyName = (identifier as unknown) as string;
49+
identifier = internalModel.identifier;
50+
instance = (internalModel._recordData as RelationshipRecordData).storeWrapper;
51+
}
52+
return relationshipsFor(instance as RecordDataStoreWrapper, identifier as StableRecordIdentifier).get(propertyName);
53+
}
2254

23-
return recordData._implicitRelationships;
55+
export function implicitRelationshipsFor(
56+
storeWrapper: RecordDataStoreWrapper,
57+
identifier: StableRecordIdentifier
58+
): RelationshipDict {
59+
return graphFor(storeWrapper).getImplicit(identifier);
2460
}
2561

26-
export function implicitRelationshipStateFor(instance: any, propertyName: string): Relationship {
27-
return implicitRelationshipsFor(instance)[propertyName];
62+
export function implicitRelationshipStateFor(
63+
storeWrapper: RecordDataStoreWrapper,
64+
identifier: StableRecordIdentifier,
65+
propertyName: string
66+
): Relationship {
67+
return implicitRelationshipsFor(storeWrapper, identifier)[propertyName];
2868
}

0 commit comments

Comments
 (0)
Please sign in to comment.