Skip to content

Commit 76c9d0a

Browse files
authored
fix: notify during replace if existing localState never previously calculated (#9251)
* fix: if array was empty, use add vs replace * fix: fix via detection instead
1 parent 489497c commit 76c9d0a

File tree

2 files changed

+39
-17
lines changed

2 files changed

+39
-17
lines changed

packages/graph/src/-private/operations/replace-related-records.ts

+11-1
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,13 @@ function replaceRelatedRecordsLocal(graph: Graph, op: ReplaceRelatedRecordsOpera
7878
const identifiers = op.value;
7979
const relationship = graph.get(op.record, op.field);
8080
assert(`expected hasMany relationship`, isHasMany(relationship));
81+
82+
// relationships for newly created records begin in the dirty state, so if updated
83+
// before flushed we would fail to notify. This check helps us avoid that.
84+
const isMaybeFirstUpdate =
85+
relationship.remoteState.length === 0 &&
86+
relationship.localState === null &&
87+
relationship.state.hasReceivedData === false;
8188
relationship.state.hasReceivedData = true;
8289
const { additions, removals } = relationship;
8390
const { inverseKey, type } = relationship.definition;
@@ -151,7 +158,10 @@ function replaceRelatedRecordsLocal(graph: Graph, op: ReplaceRelatedRecordsOpera
151158
relationship.localState = diff.finalState;
152159
relationship.isDirty = wasDirty;
153160

154-
if (!wasDirty /*&& becameDirty // TODO to guard like this we need to detect reorder when diffing local */) {
161+
if (
162+
isMaybeFirstUpdate ||
163+
!wasDirty /*&& becameDirty // TODO to guard like this we need to detect reorder when diffing local */
164+
) {
155165
notifyChange(graph, op.record, op.field);
156166
}
157167
}

tests/main/tests/integration/references/has-many-test.js

+28-16
Original file line numberDiff line numberDiff line change
@@ -9,30 +9,30 @@ import testInDebug from '@ember-data/unpublished-test-infra/test-support/test-in
99

1010
import createTrackingContext from '../../helpers/create-tracking-context';
1111

12-
module('integration/references/has-many', function (hooks) {
13-
setupRenderingTest(hooks);
12+
class Family extends Model {
13+
@hasMany('person', { async: true, inverse: 'family' }) persons;
14+
}
1415

15-
hooks.beforeEach(function () {
16-
const Family = Model.extend({
17-
persons: hasMany('person', { async: true, inverse: 'family' }),
18-
});
16+
class Person extends Model {
17+
@attr name;
18+
@belongsTo('family', { async: true, inverse: 'persons' }) family;
19+
@hasMany('pet', { async: true, inverse: null }) pets;
20+
}
1921

20-
const Person = Model.extend({
21-
name: attr(),
22-
family: belongsTo('family', { async: true, inverse: 'persons' }),
23-
pets: hasMany('pet', { async: true, inverse: null }),
24-
});
22+
class Pet extends Model {
23+
@attr name;
24+
}
2525

26-
const Pet = Model.extend({
27-
name: attr(),
28-
});
26+
module('integration/references/has-many', function (hooks) {
27+
setupRenderingTest(hooks);
2928

29+
hooks.beforeEach(function () {
3030
this.owner.register('model:family', Family);
3131
this.owner.register('model:person', Person);
3232
this.owner.register('model:pet', Pet);
3333

34-
this.owner.register('adapter:application', Adapter.extend());
35-
this.owner.register('serializer:application', class extends JSONAPISerializer {});
34+
this.owner.register('adapter:application', Adapter);
35+
this.owner.register('serializer:application', JSONAPISerializer);
3636
});
3737

3838
testInDebug("record#hasMany asserts when specified relationship doesn't exist", function (assert) {
@@ -93,6 +93,18 @@ module('integration/references/has-many', function (hooks) {
9393
assert.deepEqual(personsReference.ids(), ['1', '2']);
9494
});
9595

96+
test('ref.ids() updates when using createRecord', async function (assert) {
97+
const store = this.owner.lookup('service:store');
98+
99+
const family = store.createRecord('family');
100+
const person1 = store.createRecord('person', {});
101+
assert.strictEqual(family.hasMany('persons').ids().length, 0);
102+
103+
family.persons = [person1];
104+
105+
assert.strictEqual(family.hasMany('persons').ids().length, 1);
106+
});
107+
96108
test('record#hasMany for linked references', function (assert) {
97109
const store = this.owner.lookup('service:store');
98110

0 commit comments

Comments
 (0)