@ember-data/model 4.5.0-beta.0 → 4.7.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/addon/-private/attr.js +14 -5
- package/addon/-private/belongs-to.js +9 -5
- package/addon/-private/{system/diff-array.ts → diff-array.ts} +0 -0
- package/addon/-private/errors.ts +7 -69
- package/addon/-private/has-many.js +7 -6
- package/addon/-private/index.ts +6 -5
- package/addon/-private/legacy-data-fetch.js +370 -0
- package/addon/-private/legacy-data-utils.ts +92 -0
- package/addon/-private/legacy-relationships-support.ts +709 -0
- package/addon/-private/{system/many-array.ts → many-array.ts} +38 -33
- package/addon/-private/{system/model-for-mixin.ts → model-for-mixin.ts} +3 -3
- package/addon/-private/model.js +104 -50
- package/addon/-private/notify-changes.ts +21 -13
- package/addon/-private/{system/promise-belongs-to.ts → promise-belongs-to.ts} +9 -8
- package/addon/-private/{system/promise-many-array.ts → promise-many-array.ts} +3 -3
- package/addon/-private/record-state.ts +31 -21
- package/addon/-private/references/belongs-to.ts +585 -0
- package/addon/-private/references/has-many.ts +621 -0
- package/addon/-private/{system/relationships/relationship-meta.ts → relationship-meta.ts} +5 -5
- package/blueprints/model-test/index.js +2 -0
- package/blueprints/model-test/mocha-rfc-232-files/__root__/__path__/__test__.js +1 -1
- package/blueprints/model-test/qunit-files/__root__/__path__/__test__.js +1 -1
- package/index.js +4 -0
- package/package.json +24 -22
|
@@ -8,18 +8,20 @@ import EmberObject, { get } from '@ember/object';
|
|
|
8
8
|
|
|
9
9
|
import { all } from 'rsvp';
|
|
10
10
|
|
|
11
|
-
import type
|
|
12
|
-
import type { InternalModel } from '@ember-data/store/-private';
|
|
11
|
+
import type Store from '@ember-data/store';
|
|
13
12
|
import { PromiseArray, recordDataFor } from '@ember-data/store/-private';
|
|
14
|
-
import type
|
|
15
|
-
import type
|
|
16
|
-
import
|
|
17
|
-
import type {
|
|
18
|
-
import type {
|
|
19
|
-
import type { RecordInstance } from '@ember-data/
|
|
20
|
-
import type {
|
|
13
|
+
import type { CreateRecordProperties } from '@ember-data/store/-private/core-store';
|
|
14
|
+
import type ShimModelClass from '@ember-data/store/-private/model/shim-model-class';
|
|
15
|
+
import type { DSModelSchema } from '@ember-data/types/q/ds-model';
|
|
16
|
+
import type { Links, PaginationLinks } from '@ember-data/types/q/ember-data-json-api';
|
|
17
|
+
import type { StableRecordIdentifier } from '@ember-data/types/q/identifier';
|
|
18
|
+
import type { RecordInstance } from '@ember-data/types/q/record-instance';
|
|
19
|
+
import type { RelationshipRecordData } from '@ember-data/types/q/relationship-record-data';
|
|
20
|
+
import type { FindOptions } from '@ember-data/types/q/store';
|
|
21
|
+
import type { Dict } from '@ember-data/types/q/utils';
|
|
21
22
|
|
|
22
23
|
import diffArray from './diff-array';
|
|
24
|
+
import { LegacySupport } from './legacy-relationships-support';
|
|
23
25
|
|
|
24
26
|
interface MutableArrayWithObject<T, M = T> extends EmberObject, MutableArray<M> {}
|
|
25
27
|
const MutableArrayWithObject = EmberObject.extend(MutableArray) as unknown as new <
|
|
@@ -28,14 +30,14 @@ const MutableArrayWithObject = EmberObject.extend(MutableArray) as unknown as ne
|
|
|
28
30
|
>() => MutableArrayWithObject<T, M>;
|
|
29
31
|
|
|
30
32
|
export interface ManyArrayCreateArgs {
|
|
31
|
-
store:
|
|
33
|
+
store: Store;
|
|
32
34
|
type: ShimModelClass;
|
|
33
35
|
recordData: RelationshipRecordData;
|
|
34
36
|
key: string;
|
|
35
37
|
isPolymorphic: boolean;
|
|
36
38
|
isAsync: boolean;
|
|
37
39
|
_inverseIsAsync: boolean;
|
|
38
|
-
|
|
40
|
+
legacySupport: LegacySupport;
|
|
39
41
|
isLoaded: boolean;
|
|
40
42
|
}
|
|
41
43
|
/**
|
|
@@ -83,7 +85,7 @@ export interface ManyArrayCreateArgs {
|
|
|
83
85
|
@extends Ember.EmberObject
|
|
84
86
|
@uses Ember.MutableArray
|
|
85
87
|
*/
|
|
86
|
-
export default class ManyArray extends MutableArrayWithObject<
|
|
88
|
+
export default class ManyArray extends MutableArrayWithObject<StableRecordIdentifier, RecordInstance> {
|
|
87
89
|
declare isAsync: boolean;
|
|
88
90
|
declare isLoaded: boolean;
|
|
89
91
|
declare isPolymorphic: boolean;
|
|
@@ -95,10 +97,10 @@ export default class ManyArray extends MutableArrayWithObject<InternalModel, Rec
|
|
|
95
97
|
declare _length: number;
|
|
96
98
|
declare _meta: Dict<unknown> | null;
|
|
97
99
|
declare _links: Links | PaginationLinks | null;
|
|
98
|
-
declare currentState:
|
|
100
|
+
declare currentState: StableRecordIdentifier[];
|
|
99
101
|
declare recordData: RelationshipRecordData;
|
|
100
|
-
declare
|
|
101
|
-
declare store:
|
|
102
|
+
declare legacySupport: LegacySupport;
|
|
103
|
+
declare store: Store;
|
|
102
104
|
declare key: string;
|
|
103
105
|
declare type: DSModelSchema;
|
|
104
106
|
|
|
@@ -260,23 +262,25 @@ export default class ManyArray extends MutableArrayWithObject<InternalModel, Rec
|
|
|
260
262
|
if (this._isDirty) {
|
|
261
263
|
this.retrieveLatest();
|
|
262
264
|
}
|
|
263
|
-
let
|
|
264
|
-
if (
|
|
265
|
+
let identifier = this.currentState[index];
|
|
266
|
+
if (identifier === undefined) {
|
|
265
267
|
return;
|
|
266
268
|
}
|
|
267
269
|
|
|
268
|
-
return
|
|
270
|
+
return this.store._instanceCache.getRecord(identifier);
|
|
269
271
|
}
|
|
270
272
|
|
|
271
273
|
replace(idx: number, amt: number, objects?: RecordInstance[]) {
|
|
272
274
|
assert(`Cannot push mutations to the cache while updating the relationship from cache`, !this._isUpdating);
|
|
273
|
-
|
|
274
|
-
|
|
275
|
+
const { store } = this;
|
|
276
|
+
store._backburner.join(() => {
|
|
277
|
+
let identifiers: StableRecordIdentifier[];
|
|
275
278
|
if (amt > 0) {
|
|
276
|
-
|
|
279
|
+
identifiers = this.currentState.slice(idx, idx + amt);
|
|
277
280
|
this.recordData.removeFromHasMany(
|
|
278
281
|
this.key,
|
|
279
|
-
|
|
282
|
+
// TODO RecordData V2: recordData should take identifiers not RecordDatas
|
|
283
|
+
identifiers.map((identifier) => store._instanceCache.getRecordData(identifier))
|
|
280
284
|
);
|
|
281
285
|
}
|
|
282
286
|
if (objects) {
|
|
@@ -303,14 +307,15 @@ export default class ManyArray extends MutableArrayWithObject<InternalModel, Rec
|
|
|
303
307
|
this._isUpdating = true;
|
|
304
308
|
let jsonApi = this.recordData.getHasMany(this.key);
|
|
305
309
|
|
|
306
|
-
let
|
|
310
|
+
let identifiers: StableRecordIdentifier[] = [];
|
|
307
311
|
if (jsonApi.data) {
|
|
308
312
|
for (let i = 0; i < jsonApi.data.length; i++) {
|
|
309
|
-
|
|
310
|
-
let
|
|
313
|
+
// TODO figure out where this state comes from
|
|
314
|
+
let im = this.store._instanceCache._internalModelForResource(jsonApi.data[i]);
|
|
315
|
+
let shouldRemove = im._isDematerializing || im.isEmpty || !im.isLoaded;
|
|
311
316
|
|
|
312
317
|
if (!shouldRemove) {
|
|
313
|
-
|
|
318
|
+
identifiers.push(im.identifier);
|
|
314
319
|
}
|
|
315
320
|
}
|
|
316
321
|
}
|
|
@@ -325,19 +330,19 @@ export default class ManyArray extends MutableArrayWithObject<InternalModel, Rec
|
|
|
325
330
|
|
|
326
331
|
if (this._hasArrayObservers && !this._hasNotified) {
|
|
327
332
|
// diff to find changes
|
|
328
|
-
let diff = diffArray(this.currentState,
|
|
333
|
+
let diff = diffArray(this.currentState, identifiers);
|
|
329
334
|
// it's null if no change found
|
|
330
335
|
if (diff.firstChangeIndex !== null) {
|
|
331
336
|
// we found a change
|
|
332
337
|
this.arrayContentWillChange(diff.firstChangeIndex, diff.removedCount, diff.addedCount);
|
|
333
|
-
this._length =
|
|
334
|
-
this.currentState =
|
|
338
|
+
this._length = identifiers.length;
|
|
339
|
+
this.currentState = identifiers;
|
|
335
340
|
this.arrayContentDidChange(diff.firstChangeIndex, diff.removedCount, diff.addedCount);
|
|
336
341
|
}
|
|
337
342
|
} else {
|
|
338
343
|
this._hasNotified = false;
|
|
339
|
-
this._length =
|
|
340
|
-
this.currentState =
|
|
344
|
+
this._length = identifiers.length;
|
|
345
|
+
this.currentState = identifiers;
|
|
341
346
|
}
|
|
342
347
|
|
|
343
348
|
this._isUpdating = false;
|
|
@@ -365,9 +370,9 @@ export default class ManyArray extends MutableArrayWithObject<InternalModel, Rec
|
|
|
365
370
|
@method reload
|
|
366
371
|
@public
|
|
367
372
|
*/
|
|
368
|
-
reload(options) {
|
|
373
|
+
reload(options?: FindOptions) {
|
|
369
374
|
// TODO this is odd, we don't ask the store for anything else like this?
|
|
370
|
-
return this.
|
|
375
|
+
return this.legacySupport.reloadHasMany(this.key, options);
|
|
371
376
|
}
|
|
372
377
|
|
|
373
378
|
/**
|
|
@@ -2,9 +2,9 @@ import { getOwner } from '@ember/application';
|
|
|
2
2
|
|
|
3
3
|
import type Store from '@ember-data/store';
|
|
4
4
|
|
|
5
|
-
import Model from '
|
|
5
|
+
import Model from './model';
|
|
6
6
|
|
|
7
|
-
/*
|
|
7
|
+
/*
|
|
8
8
|
In case someone defined a relationship to a mixin, for example:
|
|
9
9
|
```
|
|
10
10
|
import Model, { belongsTo, hasMany } from '@ember-data/model';
|
|
@@ -24,7 +24,7 @@ import Model from '../model';
|
|
|
24
24
|
in this case
|
|
25
25
|
*/
|
|
26
26
|
export default function modelForMixin(store: Store, normalizedModelName: string): Model | null {
|
|
27
|
-
let owner = getOwner(store);
|
|
27
|
+
let owner: any = getOwner(store);
|
|
28
28
|
let MaybeMixin = owner.factoryFor(`mixin:${normalizedModelName}`);
|
|
29
29
|
let mixin = MaybeMixin && MaybeMixin.class;
|
|
30
30
|
if (mixin) {
|
package/addon/-private/model.js
CHANGED
|
@@ -7,28 +7,45 @@ import EmberError from '@ember/error';
|
|
|
7
7
|
import EmberObject, { get } from '@ember/object';
|
|
8
8
|
import { dependentKeyCompat } from '@ember/object/compat';
|
|
9
9
|
import { run } from '@ember/runloop';
|
|
10
|
+
import { inject as service } from '@ember/service';
|
|
10
11
|
import { isNone } from '@ember/utils';
|
|
11
12
|
import { DEBUG } from '@glimmer/env';
|
|
12
13
|
import { tracked } from '@glimmer/tracking';
|
|
13
14
|
import Ember from 'ember';
|
|
14
15
|
|
|
16
|
+
import { resolve } from 'rsvp';
|
|
17
|
+
|
|
15
18
|
import { HAS_DEBUG_PACKAGE } from '@ember-data/private-build-infra';
|
|
16
19
|
import { DEPRECATE_SAVE_PROMISE_ACCESS } from '@ember-data/private-build-infra/deprecations';
|
|
20
|
+
import { recordIdentifierFor, storeFor } from '@ember-data/store';
|
|
17
21
|
import {
|
|
18
22
|
coerceId,
|
|
19
23
|
deprecatedPromiseObject,
|
|
20
24
|
errorsArrayToHash,
|
|
21
25
|
InternalModel,
|
|
22
|
-
PromiseObject,
|
|
23
26
|
recordDataFor,
|
|
27
|
+
WeakCache,
|
|
24
28
|
} from '@ember-data/store/-private';
|
|
25
29
|
|
|
26
30
|
import Errors from './errors';
|
|
31
|
+
import { LegacySupport } from './legacy-relationships-support';
|
|
32
|
+
import notifyChanges from './notify-changes';
|
|
27
33
|
import RecordState, { peekTag, tagged } from './record-state';
|
|
28
|
-
import { relationshipFromMeta } from './
|
|
34
|
+
import { relationshipFromMeta } from './relationship-meta';
|
|
29
35
|
|
|
30
36
|
const { changeProperties } = Ember;
|
|
37
|
+
export const LEGACY_SUPPORT = new WeakCache(DEBUG ? 'legacy-relationships' : '');
|
|
38
|
+
LEGACY_SUPPORT._generator = (record) => {
|
|
39
|
+
const identifier = recordIdentifierFor(record);
|
|
40
|
+
let support = LEGACY_SUPPORT.get(identifier);
|
|
41
|
+
|
|
42
|
+
if (!support) {
|
|
43
|
+
support = new LegacySupport(record);
|
|
44
|
+
LEGACY_SUPPORT.set(identifier, support);
|
|
45
|
+
}
|
|
31
46
|
|
|
47
|
+
return support;
|
|
48
|
+
};
|
|
32
49
|
function findPossibleInverses(type, inverseType, name, relationshipsSoFar) {
|
|
33
50
|
let possibleRelationships = relationshipsSoFar || [];
|
|
34
51
|
|
|
@@ -104,21 +121,38 @@ function computeOnce(target, key, desc) {
|
|
|
104
121
|
@extends Ember.EmberObject
|
|
105
122
|
*/
|
|
106
123
|
class Model extends EmberObject {
|
|
124
|
+
@service store;
|
|
125
|
+
|
|
107
126
|
init(options = {}) {
|
|
127
|
+
if (DEBUG && !options._secretInit && !options._internalModel && !options._createProps) {
|
|
128
|
+
throw new EmberError(
|
|
129
|
+
'You should not call `create` on a model. Instead, call `store.createRecord` with the attributes you would like to set.'
|
|
130
|
+
);
|
|
131
|
+
}
|
|
108
132
|
const createProps = options._createProps;
|
|
133
|
+
const _secretInit = options._secretInit;
|
|
109
134
|
delete options._createProps;
|
|
135
|
+
delete options._secretInit;
|
|
110
136
|
super.init(options);
|
|
111
137
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
throw new EmberError(
|
|
115
|
-
'You should not call `create` on a model. Instead, call `store.createRecord` with the attributes you would like to set.'
|
|
116
|
-
);
|
|
117
|
-
}
|
|
118
|
-
}
|
|
138
|
+
_secretInit(this);
|
|
139
|
+
this.___recordState = DEBUG ? new RecordState(this) : null;
|
|
119
140
|
|
|
120
|
-
this.___recordState = new RecordState(this);
|
|
121
141
|
this.setProperties(createProps);
|
|
142
|
+
|
|
143
|
+
// TODO pass something in such that we don't need internalModel
|
|
144
|
+
// to get this info
|
|
145
|
+
let store = storeFor(this);
|
|
146
|
+
let notifications = store._notificationManager;
|
|
147
|
+
let identity = recordIdentifierFor(this);
|
|
148
|
+
|
|
149
|
+
notifications.subscribe(identity, (identifier, type, key) => {
|
|
150
|
+
notifyChanges(identifier, type, key, this, store);
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
willDestroy() {
|
|
155
|
+
LEGACY_SUPPORT.get(this)?.destroy();
|
|
122
156
|
}
|
|
123
157
|
|
|
124
158
|
/**
|
|
@@ -389,9 +423,9 @@ class Model extends EmberObject {
|
|
|
389
423
|
Example
|
|
390
424
|
|
|
391
425
|
```javascript
|
|
392
|
-
record.
|
|
426
|
+
record.isReloading; // false
|
|
393
427
|
record.reload();
|
|
394
|
-
record.
|
|
428
|
+
record.isReloading; // true
|
|
395
429
|
```
|
|
396
430
|
|
|
397
431
|
@property isReloading
|
|
@@ -446,8 +480,17 @@ class Model extends EmberObject {
|
|
|
446
480
|
@private
|
|
447
481
|
@type {Object}
|
|
448
482
|
*/
|
|
483
|
+
// TODO we can probably make this a computeOnce
|
|
484
|
+
// we likely do not need to notify the currentState root anymore
|
|
449
485
|
@tagged
|
|
450
486
|
get currentState() {
|
|
487
|
+
// descriptors are called with the wrong `this` context during mergeMixins
|
|
488
|
+
// when using legacy/classic ember classes. Basically: lazy in prod and eager in dev.
|
|
489
|
+
// so we do this to try to steer folks to the nicer "dont user currentState"
|
|
490
|
+
// error.
|
|
491
|
+
if (!DEBUG && !this.___recordState) {
|
|
492
|
+
this.___recordState = new RecordState(this);
|
|
493
|
+
}
|
|
451
494
|
return this.___recordState;
|
|
452
495
|
}
|
|
453
496
|
set currentState(_v) {
|
|
@@ -521,16 +564,7 @@ class Model extends EmberObject {
|
|
|
521
564
|
*/
|
|
522
565
|
@computeOnce
|
|
523
566
|
get errors() {
|
|
524
|
-
let errors = Errors.create();
|
|
525
|
-
|
|
526
|
-
errors._registerHandlers(
|
|
527
|
-
() => {
|
|
528
|
-
this._internalModel.send('becameInvalid');
|
|
529
|
-
},
|
|
530
|
-
() => {
|
|
531
|
-
this._internalModel.send('becameValid');
|
|
532
|
-
}
|
|
533
|
-
);
|
|
567
|
+
let errors = Errors.create({ __record: this });
|
|
534
568
|
// TODO we should unify how errors gets populated
|
|
535
569
|
// with the code managing the update. Probably a
|
|
536
570
|
// lazy flush similar to retrieveLatest in ManyArray
|
|
@@ -543,7 +577,7 @@ class Model extends EmberObject {
|
|
|
543
577
|
let errorKeys = Object.keys(errorsHash);
|
|
544
578
|
|
|
545
579
|
for (let i = 0; i < errorKeys.length; i++) {
|
|
546
|
-
errors.
|
|
580
|
+
errors.add(errorKeys[i], errorsHash[errorKeys[i]]);
|
|
547
581
|
}
|
|
548
582
|
}
|
|
549
583
|
}
|
|
@@ -582,7 +616,7 @@ class Model extends EmberObject {
|
|
|
582
616
|
@return {Object} an object whose values are primitive JSON values only
|
|
583
617
|
*/
|
|
584
618
|
serialize(options) {
|
|
585
|
-
return this.
|
|
619
|
+
return storeFor(this)._instanceCache.createSnapshot(recordIdentifierFor(this)).serialize(options);
|
|
586
620
|
}
|
|
587
621
|
|
|
588
622
|
/*
|
|
@@ -635,7 +669,10 @@ class Model extends EmberObject {
|
|
|
635
669
|
@public
|
|
636
670
|
*/
|
|
637
671
|
deleteRecord() {
|
|
638
|
-
|
|
672
|
+
// ensure we've populated currentState prior to deleting a new record
|
|
673
|
+
if (this.currentState) {
|
|
674
|
+
storeFor(this).deleteRecord(this);
|
|
675
|
+
}
|
|
639
676
|
}
|
|
640
677
|
|
|
641
678
|
/**
|
|
@@ -684,7 +721,11 @@ class Model extends EmberObject {
|
|
|
684
721
|
successfully or rejected if the adapter returns with an error.
|
|
685
722
|
*/
|
|
686
723
|
destroyRecord(options) {
|
|
724
|
+
const { isNew } = this.currentState;
|
|
687
725
|
this.deleteRecord();
|
|
726
|
+
if (isNew) {
|
|
727
|
+
return resolve(this);
|
|
728
|
+
}
|
|
688
729
|
return this.save(options).then((_) => {
|
|
689
730
|
run(() => {
|
|
690
731
|
this.unloadRecord();
|
|
@@ -701,10 +742,10 @@ class Model extends EmberObject {
|
|
|
701
742
|
@public
|
|
702
743
|
*/
|
|
703
744
|
unloadRecord() {
|
|
704
|
-
if (this.isDestroyed) {
|
|
745
|
+
if (this.currentState.isNew && (this.isDestroyed || this.isDestroying)) {
|
|
705
746
|
return;
|
|
706
747
|
}
|
|
707
|
-
this.
|
|
748
|
+
storeFor(this).unloadRecord(this);
|
|
708
749
|
}
|
|
709
750
|
|
|
710
751
|
/**
|
|
@@ -793,16 +834,18 @@ class Model extends EmberObject {
|
|
|
793
834
|
@public
|
|
794
835
|
*/
|
|
795
836
|
rollbackAttributes() {
|
|
837
|
+
const { currentState } = this;
|
|
796
838
|
this._internalModel.rollbackAttributes();
|
|
797
|
-
|
|
839
|
+
currentState.cleanErrorRequests();
|
|
798
840
|
}
|
|
799
841
|
|
|
800
842
|
/**
|
|
801
843
|
@method _createSnapshot
|
|
802
844
|
@private
|
|
803
845
|
*/
|
|
846
|
+
// TODO @deprecate in favor of a public API or examples of how to test successfully
|
|
804
847
|
_createSnapshot() {
|
|
805
|
-
return this.
|
|
848
|
+
return storeFor(this)._instanceCache.createSnapshot(recordIdentifierFor(this));
|
|
806
849
|
}
|
|
807
850
|
|
|
808
851
|
toStringExtension() {
|
|
@@ -854,9 +897,16 @@ class Model extends EmberObject {
|
|
|
854
897
|
successfully or rejected if the adapter returns with an error.
|
|
855
898
|
*/
|
|
856
899
|
save(options) {
|
|
857
|
-
|
|
900
|
+
let promise;
|
|
901
|
+
|
|
902
|
+
if (this.currentState.isNew && this.currentState.isDeleted) {
|
|
903
|
+
promise = resolve(this);
|
|
904
|
+
} else {
|
|
905
|
+
promise = storeFor(this).saveRecord(this, options);
|
|
906
|
+
}
|
|
907
|
+
|
|
858
908
|
if (DEPRECATE_SAVE_PROMISE_ACCESS) {
|
|
859
|
-
return deprecatedPromiseObject(
|
|
909
|
+
return deprecatedPromiseObject(promise);
|
|
860
910
|
}
|
|
861
911
|
|
|
862
912
|
return promise;
|
|
@@ -891,24 +941,28 @@ class Model extends EmberObject {
|
|
|
891
941
|
adapter returns successfully or rejected if the adapter returns
|
|
892
942
|
with an error.
|
|
893
943
|
*/
|
|
894
|
-
reload(
|
|
895
|
-
let
|
|
944
|
+
reload(_options) {
|
|
945
|
+
let options = {};
|
|
896
946
|
|
|
897
|
-
if (typeof
|
|
898
|
-
|
|
899
|
-
adapterOptions: options.adapterOptions,
|
|
900
|
-
};
|
|
947
|
+
if (typeof _options === 'object' && _options !== null && _options.adapterOptions) {
|
|
948
|
+
options.adapterOptions = _options.adapterOptions;
|
|
901
949
|
}
|
|
902
950
|
|
|
951
|
+
options.isReloading = true;
|
|
952
|
+
let identifier = recordIdentifierFor(this);
|
|
953
|
+
assert(`You cannot reload a record without an ID`, identifier.id);
|
|
903
954
|
this.isReloading = true;
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
.
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
955
|
+
const promise = storeFor(this)
|
|
956
|
+
._fetchManager.scheduleFetch(identifier, options)
|
|
957
|
+
.then(() => this)
|
|
958
|
+
.finally(() => {
|
|
959
|
+
this.isReloading = false;
|
|
960
|
+
});
|
|
961
|
+
|
|
962
|
+
if (DEPRECATE_SAVE_PROMISE_ACCESS) {
|
|
963
|
+
return deprecatedPromiseObject(promise);
|
|
964
|
+
}
|
|
965
|
+
return promise;
|
|
912
966
|
}
|
|
913
967
|
|
|
914
968
|
attr() {
|
|
@@ -983,7 +1037,7 @@ class Model extends EmberObject {
|
|
|
983
1037
|
@return {BelongsToReference} reference for this relationship
|
|
984
1038
|
*/
|
|
985
1039
|
belongsTo(name) {
|
|
986
|
-
return this.
|
|
1040
|
+
return LEGACY_SUPPORT.lookup(this).referenceFor('belongsTo', name);
|
|
987
1041
|
}
|
|
988
1042
|
|
|
989
1043
|
/**
|
|
@@ -1046,7 +1100,7 @@ class Model extends EmberObject {
|
|
|
1046
1100
|
@return {HasManyReference} reference for this relationship
|
|
1047
1101
|
*/
|
|
1048
1102
|
hasMany(name) {
|
|
1049
|
-
return this.
|
|
1103
|
+
return LEGACY_SUPPORT.lookup(this).referenceFor('hasMany', name);
|
|
1050
1104
|
}
|
|
1051
1105
|
|
|
1052
1106
|
/**
|
|
@@ -1111,7 +1165,7 @@ class Model extends EmberObject {
|
|
|
1111
1165
|
}
|
|
1112
1166
|
|
|
1113
1167
|
inverseFor(key) {
|
|
1114
|
-
return this.constructor.inverseFor(key, this
|
|
1168
|
+
return this.constructor.inverseFor(key, storeFor(this));
|
|
1115
1169
|
}
|
|
1116
1170
|
|
|
1117
1171
|
eachAttribute(callback, binding) {
|
|
@@ -1938,8 +1992,8 @@ class Model extends EmberObject {
|
|
|
1938
1992
|
// this is required to prevent `init` from passing
|
|
1939
1993
|
// the values initialized during create to `setUnknownProperty`
|
|
1940
1994
|
Model.prototype._internalModel = null;
|
|
1941
|
-
Model.prototype.store = null;
|
|
1942
1995
|
Model.prototype._createProps = null;
|
|
1996
|
+
Model.prototype._secretInit = null;
|
|
1943
1997
|
|
|
1944
1998
|
if (HAS_DEBUG_PACKAGE) {
|
|
1945
1999
|
/**
|
|
@@ -2040,7 +2094,7 @@ if (DEBUG) {
|
|
|
2040
2094
|
|
|
2041
2095
|
let ourDescriptor = lookupDescriptor(Model.prototype, 'currentState');
|
|
2042
2096
|
let theirDescriptor = lookupDescriptor(this, 'currentState');
|
|
2043
|
-
let realState = this.___recordState
|
|
2097
|
+
let realState = this.___recordState;
|
|
2044
2098
|
if (ourDescriptor.get !== theirDescriptor.get || realState !== this.currentState) {
|
|
2045
2099
|
throw new Error(
|
|
2046
2100
|
`'currentState' is a reserved property name on instances of classes extending Model. Please choose a different property name for ${this.constructor.toString()}`
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
import { cacheFor } from '@ember/object/internals';
|
|
2
2
|
|
|
3
|
-
import type
|
|
4
|
-
import type { NotificationType } from '@ember-data/store/-private/
|
|
5
|
-
import type { StableRecordIdentifier } from '@ember-data/
|
|
3
|
+
import type Store from '@ember-data/store';
|
|
4
|
+
import type { NotificationType } from '@ember-data/store/-private/record-notification-manager';
|
|
5
|
+
import type { StableRecordIdentifier } from '@ember-data/types/q/identifier';
|
|
6
6
|
|
|
7
|
-
type Model
|
|
7
|
+
import type Model from './model';
|
|
8
|
+
import { LEGACY_SUPPORT } from './model';
|
|
8
9
|
|
|
9
10
|
export default function notifyChanges(
|
|
10
11
|
identifier: StableRecordIdentifier,
|
|
11
12
|
value: NotificationType,
|
|
12
13
|
key: string | undefined,
|
|
13
14
|
record: Model,
|
|
14
|
-
store:
|
|
15
|
+
store: Store
|
|
15
16
|
) {
|
|
16
17
|
if (value === 'attributes') {
|
|
17
18
|
if (key) {
|
|
@@ -24,10 +25,10 @@ export default function notifyChanges(
|
|
|
24
25
|
} else if (value === 'relationships') {
|
|
25
26
|
if (key) {
|
|
26
27
|
let meta = record.constructor.relationshipsByName.get(key);
|
|
27
|
-
notifyRelationship(
|
|
28
|
+
notifyRelationship(identifier, key, record, meta);
|
|
28
29
|
} else {
|
|
29
30
|
record.eachRelationship((key, meta) => {
|
|
30
|
-
notifyRelationship(
|
|
31
|
+
notifyRelationship(identifier, key, record, meta);
|
|
31
32
|
});
|
|
32
33
|
}
|
|
33
34
|
} else if (value === 'identity') {
|
|
@@ -35,12 +36,19 @@ export default function notifyChanges(
|
|
|
35
36
|
}
|
|
36
37
|
}
|
|
37
38
|
|
|
38
|
-
function notifyRelationship(
|
|
39
|
-
let internalModel = store._internalModelForResource(identifier);
|
|
39
|
+
function notifyRelationship(identifier: StableRecordIdentifier, key: string, record: Model, meta) {
|
|
40
40
|
if (meta.kind === 'belongsTo') {
|
|
41
41
|
record.notifyPropertyChange(key);
|
|
42
42
|
} else if (meta.kind === 'hasMany') {
|
|
43
|
-
let
|
|
43
|
+
let support = LEGACY_SUPPORT.get(identifier);
|
|
44
|
+
let manyArray = support && support._manyArrayCache[key];
|
|
45
|
+
let hasPromise = support && support._relationshipPromisesCache[key];
|
|
46
|
+
|
|
47
|
+
if (manyArray && hasPromise) {
|
|
48
|
+
// do nothing, we will notify the ManyArray directly
|
|
49
|
+
// once the fetch has completed.
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
44
52
|
|
|
45
53
|
if (manyArray) {
|
|
46
54
|
manyArray.notify();
|
|
@@ -55,10 +63,10 @@ function notifyRelationship(store: CoreStore, identifier: StableRecordIdentifier
|
|
|
55
63
|
}
|
|
56
64
|
}
|
|
57
65
|
|
|
58
|
-
function notifyAttribute(store:
|
|
66
|
+
function notifyAttribute(store: Store, identifier: StableRecordIdentifier, key: string, record: Model) {
|
|
59
67
|
let currentValue = cacheFor(record, key);
|
|
60
|
-
|
|
61
|
-
if (currentValue !==
|
|
68
|
+
|
|
69
|
+
if (currentValue !== store._instanceCache.getRecordData(identifier).getAttr(key)) {
|
|
62
70
|
record.notifyPropertyChange(key);
|
|
63
71
|
}
|
|
64
72
|
}
|
|
@@ -3,16 +3,17 @@ import { computed } from '@ember/object';
|
|
|
3
3
|
import type PromiseProxyMixin from '@ember/object/promise-proxy-mixin';
|
|
4
4
|
import type ObjectProxy from '@ember/object/proxy';
|
|
5
5
|
|
|
6
|
-
import type
|
|
6
|
+
import type Store from '@ember-data/store';
|
|
7
7
|
import { PromiseObject } from '@ember-data/store/-private';
|
|
8
|
-
import type
|
|
9
|
-
import type {
|
|
10
|
-
|
|
8
|
+
import type { RecordInstance } from '@ember-data/types/q/record-instance';
|
|
9
|
+
import type { Dict } from '@ember-data/types/q/utils';
|
|
10
|
+
|
|
11
|
+
import { LegacySupport } from './legacy-relationships-support';
|
|
11
12
|
|
|
12
13
|
export interface BelongsToProxyMeta {
|
|
13
14
|
key: string;
|
|
14
|
-
store:
|
|
15
|
-
|
|
15
|
+
store: Store;
|
|
16
|
+
legacySupport: LegacySupport;
|
|
16
17
|
modelName: string;
|
|
17
18
|
}
|
|
18
19
|
export interface BelongsToProxyCreateArgs {
|
|
@@ -63,8 +64,8 @@ class PromiseBelongsTo extends Extended<RecordInstance> {
|
|
|
63
64
|
|
|
64
65
|
async reload(options: Dict<unknown>): Promise<this> {
|
|
65
66
|
assert('You are trying to reload an async belongsTo before it has been created', this.content !== undefined);
|
|
66
|
-
let { key,
|
|
67
|
-
await
|
|
67
|
+
let { key, legacySupport } = this._belongsToState;
|
|
68
|
+
await legacySupport.reloadBelongsTo(key, options);
|
|
68
69
|
return this;
|
|
69
70
|
}
|
|
70
71
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import ArrayMixin from '@ember/array';
|
|
1
|
+
import ArrayMixin, { NativeArray } from '@ember/array';
|
|
2
2
|
import type ArrayProxy from '@ember/array/proxy';
|
|
3
3
|
import { assert } from '@ember/debug';
|
|
4
4
|
import { dependentKeyCompat } from '@ember/object/compat';
|
|
@@ -10,7 +10,7 @@ import { resolve } from 'rsvp';
|
|
|
10
10
|
import type { ManyArray } from 'ember-data/-private';
|
|
11
11
|
|
|
12
12
|
import type { InternalModel } from '@ember-data/store/-private';
|
|
13
|
-
import type { RecordInstance } from '@ember-data/
|
|
13
|
+
import type { RecordInstance } from '@ember-data/types/q/record-instance';
|
|
14
14
|
|
|
15
15
|
export interface HasManyProxyCreateArgs {
|
|
16
16
|
promise: Promise<ManyArray>;
|
|
@@ -55,7 +55,7 @@ export default class PromiseManyArray {
|
|
|
55
55
|
|
|
56
56
|
const meta = Ember.meta(this);
|
|
57
57
|
meta.hasMixin = (mixin: Object) => {
|
|
58
|
-
if (mixin === ArrayMixin) {
|
|
58
|
+
if (mixin === NativeArray || mixin === ArrayMixin) {
|
|
59
59
|
return true;
|
|
60
60
|
}
|
|
61
61
|
return false;
|