Skip to content

Commit

Permalink
update test and fix issue
Browse files Browse the repository at this point in the history
  • Loading branch information
runspired committed May 26, 2021
1 parent 2b6a5ed commit 6ee83d5
Show file tree
Hide file tree
Showing 7 changed files with 88 additions and 56 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ module('integration/relationships/one_to_many_test - OneToMany relationships', f
});
});

test("Adapter's findBelongsTo must not be hit when the record is included with its owner", function (assert) {
test("Adapter's findBelongsTo must not be hit when the record is included with its owner", async function (assert) {
let store = this.owner.lookup('service:store');
assert.expect(1);

Expand All @@ -100,63 +100,49 @@ module('integration/relationships/one_to_many_test - OneToMany relationships', f
})
);

var user;
run(function () {
user = store.push({
data: {
id: '1',
type: 'user',
const user = store.push({
data: {
id: '1',
type: 'user',
attributes: {
name: 'Stanley',
},
relationships: {
messages: {
links: {
self: 'users/1/relationships/messages',
related: 'users/1/posts',
},
data: [
{
id: '2',
type: 'message',
},
],
},
},
},
included: [
{
id: '2',
type: 'message',
attributes: {
name: 'Stanley',
title: 'EmberFest was great',
},
relationships: {
messages: {
user: {
links: {
self: 'users/1/relationships/messages',
related: 'users/1/posts',
self: 'messages/1/relationships/user',
related: 'messages/1/author',
},
data: [
{
id: '2',
type: 'message',
},
],
},
},
},
included: [
{
id: '2',
type: 'message',
attributes: {
title: 'EmberFest was great',
},
relationships: {
user: {
// data: {
// id: '1',
// type: 'user',
// },
links: {
self: 'messages/1/relationships/user',
related: 'messages/1/author',
},
},
},
},
],
});
});
run(function () {
user.get('messages').then(function (fetchedMessages) {
fetchedMessages
.toArray()[0]
.get('user')
.then(function (fetchedUser) {
assert.equal(fetchedUser, user, 'User relationship was set up correctly');
});
});
],
});
const messages = await user.messages;
const messageUser = await messages.objectAt(0).user;
assert.true(messageUser === user, 'User relationship was set up correctly');
});

test('Relationship is available from the belongsTo side even if only loaded from the hasMany side - sync', function (assert) {
Expand Down
17 changes: 17 additions & 0 deletions packages/record-data/addon/-private/graph/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ export class Graph {
deletions: DeleteRecordOperation[];
};
declare _updatedRelationships: Set<ManyRelationship>;
declare _transaction: Set<ManyRelationship | BelongsToRelationship> | null;

constructor(store: RecordDataStoreWrapper) {
this._definitionCache = Object.create(null);
Expand All @@ -90,6 +91,7 @@ export class Graph {
this._willSyncLocal = false;
this._pushedUpdates = { belongsTo: [], hasMany: [], deletions: [] };
this._updatedRelationships = new Set();
this._transaction = null;
}

has(identifier: StableRecordIdentifier, propertyName: string): boolean {
Expand Down Expand Up @@ -307,6 +309,7 @@ export class Graph {
if (!this._willSyncRemote) {
return;
}
this._transaction = new Set();
this._willSyncRemote = false;
const { deletions, hasMany, belongsTo } = this._pushedUpdates;
this._pushedUpdates.deletions = [];
Expand All @@ -324,6 +327,20 @@ export class Graph {
for (let i = 0; i < belongsTo.length; i++) {
this.update(belongsTo[i], true);
}
this._finalize();
}

_addToTransaction(relationship: ManyRelationship | BelongsToRelationship) {
assert(`expected a transaction`, this._transaction !== null);
relationship.transactionRef++;
this._transaction.add(relationship);
}

_finalize() {
if (this._transaction) {
this._transaction.forEach((v) => (v.transactionRef = 0));
this._transaction = null;
}
}

_flushLocalQueue() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ export default function replaceRelatedRecord(graph: Graph, op: ReplaceRelatedRec
`You can only '${op.op}' on a belongsTo relationship. ${op.record.type}.${op.field} is a ${relationship.definition.kind}`,
isBelongsTo(relationship)
);
if (isRemote) {
graph._addToTransaction(relationship);
}
const { definition, state } = relationship;
const prop = isRemote ? 'remoteState' : 'localState';
const existingState: StableRecordIdentifier | null = relationship[prop];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,9 @@ function replaceRelatedRecordsRemote(graph: Graph, op: ReplaceRelatedRecordsOper
`You can only '${op.op}' on a hasMany relationship. ${op.record.type}.${op.field} is a ${relationship.definition.kind}`,
isHasMany(relationship)
);
if (isRemote) {
graph._addToTransaction(relationship);
}
relationship.state.hasReceivedData = true;

const newValues = Object.create(null);
Expand Down Expand Up @@ -241,6 +244,7 @@ export function addToInverse(
relationship.state.isEmpty = false;

if (isRemote) {
graph._addToTransaction(relationship);
if (relationship.remoteState !== null) {
removeFromInverse(graph, relationship.remoteState, relationship.definition.inverseKey, identifier, isRemote);
}
Expand All @@ -257,6 +261,7 @@ export function addToInverse(
} else if (isHasMany(relationship)) {
if (isRemote) {
if (!relationship.canonicalMembers.has(value)) {
graph._addToTransaction(relationship);
relationship.canonicalState.push(value);
relationship.canonicalMembers.add(value);
relationship.state.hasReceivedData = true;
Expand Down Expand Up @@ -291,6 +296,7 @@ export function removeFromInverse(
if (isBelongsTo(relationship)) {
relationship.state.isEmpty = true;
if (isRemote) {
graph._addToTransaction(relationship);
relationship.remoteState = null;
}
if (relationship.localState === value) {
Expand All @@ -299,6 +305,7 @@ export function removeFromInverse(
}
} else if (isHasMany(relationship)) {
if (isRemote) {
graph._addToTransaction(relationship);
let index = relationship.canonicalState.indexOf(value);
if (index !== -1) {
relationship.canonicalMembers.delete(value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export default function updateRelationshipOperation(graph: Graph, op: UpdateRela
const payload = op.value;

let hasRelationshipDataProperty: boolean = false;
let hasLink: boolean = false;
let hasUpdatedLink: boolean = false;

if (payload.meta) {
relationship.meta = payload.meta;
Expand Down Expand Up @@ -104,7 +104,7 @@ export default function updateRelationshipOperation(graph: Graph, op: UpdateRela
`You have pushed a record of type '${identifier.type}' with '${definition.key}' as a link, but the value of that link is not a string.`,
typeof relatedLink.href === 'string' || relatedLink.href === null
);
hasLink = true;
hasUpdatedLink = true;
}
}
}
Expand All @@ -128,17 +128,32 @@ export default function updateRelationshipOperation(graph: Graph, op: UpdateRela
if (hasRelationshipDataProperty) {
let relationshipIsEmpty = payload.data === null || (Array.isArray(payload.data) && payload.data.length === 0);

// we don't need to notify here as the update op we pushed in above will notify once
// membership is in the correct state.
relationship.state.hasReceivedData = true;
relationship.state.isStale = false;
relationship.state.hasDematerializedInverse = false;
relationship.state.isEmpty = relationshipIsEmpty;
} else if (hasLink) {
relationship.state.isStale = true;
} else if (hasUpdatedLink) {
// only notify stale if we have not previously received membership data.
// within this same transaction
// this prevents refetching when only one side of the relationship in the
// payload contains the info while the other side contains just a link
// this only works when the side with just a link is a belongsTo, as we
// don't know if a hasMany has full information or not.
// see #7049 for context.
if (isCollection || !relationship.state.hasReceivedData || relationship.transactionRef === 0) {
relationship.state.isStale = true;

if (isHasMany(relationship)) {
relationship.notifyHasManyChange();
if (isHasMany(relationship)) {
relationship.notifyHasManyChange();
} else {
relationship.notifyBelongsToChange();
}
} else {
relationship.notifyBelongsToChange();
relationship.state.isStale = false;
}
} else {
relationship.state.isStale = false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ type PaginationLinks = import('@ember-data/store/-private/ts-interfaces/ember-da
export default class BelongsToRelationship {
declare localState: StableRecordIdentifier | null;
declare remoteState: StableRecordIdentifier | null;
declare transactionRef: number;

declare graph: Graph;
declare store: RecordDataStoreWrapper;
Expand All @@ -36,6 +37,7 @@ export default class BelongsToRelationship {
this.definition = definition;
this.identifier = identifier;
this._state = null;
this.transactionRef = 0;

this.meta = null;
this.links = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export default class ManyRelationship {
declare definition: UpgradedMeta;
declare identifier: StableRecordIdentifier;
declare _state: RelationshipState | null;
declare transactionRef: number;

declare members: Set<StableRecordIdentifier>;
declare canonicalMembers: Set<StableRecordIdentifier>;
Expand All @@ -38,6 +39,7 @@ export default class ManyRelationship {
this.definition = definition;
this.identifier = identifier;
this._state = null;
this.transactionRef = 0;

this.members = new Set<StableRecordIdentifier>();
this.canonicalMembers = new Set<StableRecordIdentifier>();
Expand Down

0 comments on commit 6ee83d5

Please sign in to comment.