@ember-data/model 4.7.0-beta.1 → 4.7.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 +9 -24
- package/addon/-private/belongs-to.js +87 -25
- package/addon/-private/deprecated-promise-proxy.ts +54 -0
- package/addon/-private/errors.ts +6 -6
- package/addon/-private/has-many.js +84 -22
- package/addon/-private/legacy-data-fetch.js +35 -13
- package/addon/-private/legacy-data-utils.ts +1 -1
- package/addon/-private/legacy-relationships-support.ts +279 -218
- package/addon/-private/many-array.ts +216 -242
- package/addon/-private/model-for-mixin.ts +2 -4
- package/addon/-private/model.js +565 -172
- package/addon/-private/notify-changes.ts +2 -2
- package/addon/-private/promise-belongs-to.ts +1 -1
- package/addon/-private/promise-many-array.ts +204 -124
- package/addon/-private/promise-proxy-base.js +4 -0
- package/addon/-private/record-state.ts +63 -46
- package/addon/-private/references/belongs-to.ts +65 -38
- package/addon/-private/references/has-many.ts +86 -55
- package/addon/-private/relationship-meta.ts +8 -26
- package/index.js +3 -0
- package/package.json +12 -8
package/addon/-private/model.js
CHANGED
|
@@ -2,13 +2,11 @@
|
|
|
2
2
|
@module @ember-data/model
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import { assert, warn } from '@ember/debug';
|
|
5
|
+
import { assert, deprecate, warn } from '@ember/debug';
|
|
6
6
|
import EmberError from '@ember/error';
|
|
7
|
-
import EmberObject
|
|
7
|
+
import EmberObject 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';
|
|
11
|
-
import { isNone } from '@ember/utils';
|
|
12
10
|
import { DEBUG } from '@glimmer/env';
|
|
13
11
|
import { tracked } from '@glimmer/tracking';
|
|
14
12
|
import Ember from 'ember';
|
|
@@ -16,17 +14,17 @@ import Ember from 'ember';
|
|
|
16
14
|
import { resolve } from 'rsvp';
|
|
17
15
|
|
|
18
16
|
import { HAS_DEBUG_PACKAGE } from '@ember-data/private-build-infra';
|
|
19
|
-
import { DEPRECATE_SAVE_PROMISE_ACCESS } from '@ember-data/private-build-infra/deprecations';
|
|
20
|
-
import { recordIdentifierFor, storeFor } from '@ember-data/store';
|
|
21
17
|
import {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
} from '@ember-data/store
|
|
18
|
+
DEPRECATE_EARLY_STATIC,
|
|
19
|
+
DEPRECATE_MODEL_REOPEN,
|
|
20
|
+
DEPRECATE_NON_EXPLICIT_POLYMORPHISM,
|
|
21
|
+
DEPRECATE_RELATIONSHIPS_WITHOUT_INVERSE,
|
|
22
|
+
DEPRECATE_SAVE_PROMISE_ACCESS,
|
|
23
|
+
} from '@ember-data/private-build-infra/deprecations';
|
|
24
|
+
import { recordIdentifierFor, storeFor } from '@ember-data/store';
|
|
25
|
+
import { coerceId, recordDataFor } from '@ember-data/store/-private';
|
|
29
26
|
|
|
27
|
+
import { deprecatedPromiseObject } from './deprecated-promise-proxy';
|
|
30
28
|
import Errors from './errors';
|
|
31
29
|
import { LegacySupport } from './legacy-relationships-support';
|
|
32
30
|
import notifyChanges from './notify-changes';
|
|
@@ -34,18 +32,21 @@ import RecordState, { peekTag, tagged } from './record-state';
|
|
|
34
32
|
import { relationshipFromMeta } from './relationship-meta';
|
|
35
33
|
|
|
36
34
|
const { changeProperties } = Ember;
|
|
37
|
-
export const LEGACY_SUPPORT = new
|
|
38
|
-
|
|
35
|
+
export const LEGACY_SUPPORT = new Map();
|
|
36
|
+
|
|
37
|
+
export function lookupLegacySupport(record) {
|
|
39
38
|
const identifier = recordIdentifierFor(record);
|
|
40
39
|
let support = LEGACY_SUPPORT.get(identifier);
|
|
41
40
|
|
|
42
41
|
if (!support) {
|
|
43
42
|
support = new LegacySupport(record);
|
|
44
43
|
LEGACY_SUPPORT.set(identifier, support);
|
|
44
|
+
LEGACY_SUPPORT.set(record, support);
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
return support;
|
|
48
|
-
}
|
|
48
|
+
}
|
|
49
|
+
|
|
49
50
|
function findPossibleInverses(type, inverseType, name, relationshipsSoFar) {
|
|
50
51
|
let possibleRelationships = relationshipsSoFar || [];
|
|
51
52
|
|
|
@@ -57,7 +58,7 @@ function findPossibleInverses(type, inverseType, name, relationshipsSoFar) {
|
|
|
57
58
|
let relationshipsForType = relationshipMap.get(type.modelName);
|
|
58
59
|
let relationships = Array.isArray(relationshipsForType)
|
|
59
60
|
? relationshipsForType.filter((relationship) => {
|
|
60
|
-
let optionsForRelationship =
|
|
61
|
+
let optionsForRelationship = relationship.options;
|
|
61
62
|
|
|
62
63
|
if (!optionsForRelationship.inverse && optionsForRelationship.inverse !== null) {
|
|
63
64
|
return true;
|
|
@@ -121,38 +122,57 @@ function computeOnce(target, key, desc) {
|
|
|
121
122
|
@extends Ember.EmberObject
|
|
122
123
|
*/
|
|
123
124
|
class Model extends EmberObject {
|
|
124
|
-
|
|
125
|
+
___private_notifications;
|
|
125
126
|
|
|
126
127
|
init(options = {}) {
|
|
127
|
-
if (DEBUG && !options._secretInit && !options.
|
|
128
|
+
if (DEBUG && !options._secretInit && !options._createProps) {
|
|
128
129
|
throw new EmberError(
|
|
129
130
|
'You should not call `create` on a model. Instead, call `store.createRecord` with the attributes you would like to set.'
|
|
130
131
|
);
|
|
131
132
|
}
|
|
132
133
|
const createProps = options._createProps;
|
|
133
134
|
const _secretInit = options._secretInit;
|
|
134
|
-
|
|
135
|
-
|
|
135
|
+
options._createProps = null;
|
|
136
|
+
options._secretInit = null;
|
|
137
|
+
|
|
138
|
+
let store = (this.store = _secretInit.store);
|
|
136
139
|
super.init(options);
|
|
137
140
|
|
|
138
|
-
_secretInit
|
|
141
|
+
let identity = _secretInit.identifier;
|
|
142
|
+
_secretInit.cb(this, _secretInit.recordData, identity, _secretInit.store);
|
|
143
|
+
|
|
139
144
|
this.___recordState = DEBUG ? new RecordState(this) : null;
|
|
140
145
|
|
|
141
146
|
this.setProperties(createProps);
|
|
142
147
|
|
|
143
|
-
// TODO pass something in such that we don't need internalModel
|
|
144
|
-
// to get this info
|
|
145
|
-
let store = storeFor(this);
|
|
146
148
|
let notifications = store._notificationManager;
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
notifications.subscribe(identity, (identifier, type, key) => {
|
|
149
|
+
this.___private_notifications = notifications.subscribe(identity, (identifier, type, key) => {
|
|
150
150
|
notifyChanges(identifier, type, key, this, store);
|
|
151
151
|
});
|
|
152
152
|
}
|
|
153
153
|
|
|
154
|
-
|
|
154
|
+
destroy() {
|
|
155
|
+
const identifier = recordIdentifierFor(this);
|
|
156
|
+
this.___recordState?.destroy();
|
|
157
|
+
const store = storeFor(this);
|
|
158
|
+
store._notificationManager.unsubscribe(this.___private_notifications);
|
|
159
|
+
// Legacy behavior is to notify the relationships on destroy
|
|
160
|
+
// such that they "clear". It's uncertain this behavior would
|
|
161
|
+
// be good for a new model paradigm, likely cheaper and safer
|
|
162
|
+
// to simply not notify, for this reason the store does not itself
|
|
163
|
+
// notify individual changes once the delete has been signaled,
|
|
164
|
+
// this decision is left to model instances.
|
|
165
|
+
|
|
166
|
+
this.eachRelationship((key, meta) => {
|
|
167
|
+
if (meta.kind === 'belongsTo') {
|
|
168
|
+
this.notifyPropertyChange(key);
|
|
169
|
+
}
|
|
170
|
+
});
|
|
155
171
|
LEGACY_SUPPORT.get(this)?.destroy();
|
|
172
|
+
LEGACY_SUPPORT.delete(this);
|
|
173
|
+
LEGACY_SUPPORT.delete(identifier);
|
|
174
|
+
|
|
175
|
+
super.destroy();
|
|
156
176
|
}
|
|
157
177
|
|
|
158
178
|
/**
|
|
@@ -200,10 +220,10 @@ class Model extends EmberObject {
|
|
|
200
220
|
|
|
201
221
|
```javascript
|
|
202
222
|
let record = store.createRecord('model');
|
|
203
|
-
record.
|
|
223
|
+
record.isLoaded; // true
|
|
204
224
|
|
|
205
225
|
store.findRecord('model', 1).then(function(model) {
|
|
206
|
-
model.
|
|
226
|
+
model.isLoaded; // true
|
|
207
227
|
});
|
|
208
228
|
```
|
|
209
229
|
|
|
@@ -227,12 +247,12 @@ class Model extends EmberObject {
|
|
|
227
247
|
|
|
228
248
|
```javascript
|
|
229
249
|
let record = store.createRecord('model');
|
|
230
|
-
record.
|
|
250
|
+
record.hasDirtyAttributes; // true
|
|
231
251
|
|
|
232
252
|
store.findRecord('model', 1).then(function(model) {
|
|
233
|
-
model.
|
|
253
|
+
model.hasDirtyAttributes; // false
|
|
234
254
|
model.set('foo', 'some value');
|
|
235
|
-
model.
|
|
255
|
+
model.hasDirtyAttributes; // true
|
|
236
256
|
});
|
|
237
257
|
```
|
|
238
258
|
|
|
@@ -257,11 +277,11 @@ class Model extends EmberObject {
|
|
|
257
277
|
|
|
258
278
|
```javascript
|
|
259
279
|
let record = store.createRecord('model');
|
|
260
|
-
record.
|
|
280
|
+
record.isSaving; // false
|
|
261
281
|
let promise = record.save();
|
|
262
|
-
record.
|
|
282
|
+
record.isSaving; // true
|
|
263
283
|
promise.then(function() {
|
|
264
|
-
record.
|
|
284
|
+
record.isSaving; // false
|
|
265
285
|
});
|
|
266
286
|
```
|
|
267
287
|
|
|
@@ -287,24 +307,24 @@ class Model extends EmberObject {
|
|
|
287
307
|
|
|
288
308
|
```javascript
|
|
289
309
|
let record = store.createRecord('model');
|
|
290
|
-
record.
|
|
310
|
+
record.isDeleted; // false
|
|
291
311
|
record.deleteRecord();
|
|
292
312
|
|
|
293
313
|
// Locally deleted
|
|
294
|
-
record.
|
|
295
|
-
record.
|
|
296
|
-
record.
|
|
314
|
+
record.isDeleted; // true
|
|
315
|
+
record.hasDirtyAttributes; // true
|
|
316
|
+
record.isSaving; // false
|
|
297
317
|
|
|
298
318
|
// Persisting the deletion
|
|
299
319
|
let promise = record.save();
|
|
300
|
-
record.
|
|
301
|
-
record.
|
|
320
|
+
record.isDeleted; // true
|
|
321
|
+
record.isSaving; // true
|
|
302
322
|
|
|
303
323
|
// Deletion Persisted
|
|
304
324
|
promise.then(function() {
|
|
305
|
-
record.
|
|
306
|
-
record.
|
|
307
|
-
record.
|
|
325
|
+
record.isDeleted; // true
|
|
326
|
+
record.isSaving; // false
|
|
327
|
+
record.hasDirtyAttributes; // false
|
|
308
328
|
});
|
|
309
329
|
```
|
|
310
330
|
|
|
@@ -328,10 +348,10 @@ class Model extends EmberObject {
|
|
|
328
348
|
|
|
329
349
|
```javascript
|
|
330
350
|
let record = store.createRecord('model');
|
|
331
|
-
record.
|
|
351
|
+
record.isNew; // true
|
|
332
352
|
|
|
333
353
|
record.save().then(function(model) {
|
|
334
|
-
model.
|
|
354
|
+
model.isNew; // false
|
|
335
355
|
});
|
|
336
356
|
```
|
|
337
357
|
|
|
@@ -374,7 +394,7 @@ class Model extends EmberObject {
|
|
|
374
394
|
|
|
375
395
|
```javascript
|
|
376
396
|
let record = store.createRecord('model');
|
|
377
|
-
record.
|
|
397
|
+
record.dirtyType; // 'created'
|
|
378
398
|
```
|
|
379
399
|
|
|
380
400
|
@property dirtyType
|
|
@@ -395,10 +415,10 @@ class Model extends EmberObject {
|
|
|
395
415
|
Example
|
|
396
416
|
|
|
397
417
|
```javascript
|
|
398
|
-
record.
|
|
418
|
+
record.isError; // false
|
|
399
419
|
record.set('foo', 'valid value');
|
|
400
420
|
record.save().then(null, function() {
|
|
401
|
-
record.
|
|
421
|
+
record.isError; // true
|
|
402
422
|
});
|
|
403
423
|
```
|
|
404
424
|
|
|
@@ -444,10 +464,10 @@ class Model extends EmberObject {
|
|
|
444
464
|
|
|
445
465
|
```javascript
|
|
446
466
|
let record = store.createRecord('model');
|
|
447
|
-
record.
|
|
467
|
+
record.id; // null
|
|
448
468
|
|
|
449
469
|
store.findRecord('model', 1).then(function(model) {
|
|
450
|
-
model.
|
|
470
|
+
model.id; // '1'
|
|
451
471
|
});
|
|
452
472
|
```
|
|
453
473
|
|
|
@@ -457,24 +477,37 @@ class Model extends EmberObject {
|
|
|
457
477
|
*/
|
|
458
478
|
@tagged
|
|
459
479
|
get id() {
|
|
460
|
-
//
|
|
480
|
+
// this guard exists, because some dev-only deprecation code
|
|
461
481
|
// (addListener via validatePropertyInjections) invokes toString before the
|
|
462
482
|
// object is real.
|
|
463
483
|
if (DEBUG) {
|
|
464
|
-
|
|
484
|
+
try {
|
|
485
|
+
return recordIdentifierFor(this).id;
|
|
486
|
+
} catch {
|
|
465
487
|
return void 0;
|
|
466
488
|
}
|
|
467
489
|
}
|
|
468
|
-
return this.
|
|
490
|
+
return recordIdentifierFor(this).id;
|
|
469
491
|
}
|
|
470
492
|
set id(id) {
|
|
471
493
|
const normalizedId = coerceId(id);
|
|
494
|
+
const identifier = recordIdentifierFor(this);
|
|
495
|
+
let didChange = normalizedId !== identifier.id;
|
|
496
|
+
assert(
|
|
497
|
+
`Cannot set ${identifier.type} record's id to ${id}, because id is already ${identifier.id}`,
|
|
498
|
+
!didChange || identifier.id === null
|
|
499
|
+
);
|
|
472
500
|
|
|
473
|
-
if (normalizedId !== null) {
|
|
474
|
-
this.
|
|
501
|
+
if (normalizedId !== null && didChange) {
|
|
502
|
+
this.store._instanceCache.setRecordId(identifier, normalizedId);
|
|
503
|
+
this.store._notificationManager.notify(identifier, 'identity');
|
|
475
504
|
}
|
|
476
505
|
}
|
|
477
506
|
|
|
507
|
+
toString() {
|
|
508
|
+
return `<model::${this.constructor.modelName}:${this.id}>`;
|
|
509
|
+
}
|
|
510
|
+
|
|
478
511
|
/**
|
|
479
512
|
@property currentState
|
|
480
513
|
@private
|
|
@@ -497,12 +530,6 @@ class Model extends EmberObject {
|
|
|
497
530
|
throw new Error('cannot set currentState');
|
|
498
531
|
}
|
|
499
532
|
|
|
500
|
-
/**
|
|
501
|
-
@property _internalModel
|
|
502
|
-
@private
|
|
503
|
-
@type {Object}
|
|
504
|
-
*/
|
|
505
|
-
|
|
506
533
|
/**
|
|
507
534
|
The store service instance which created this record instance
|
|
508
535
|
|
|
@@ -520,10 +547,10 @@ class Model extends EmberObject {
|
|
|
520
547
|
- `attribute` The name of the property associated with this error message
|
|
521
548
|
|
|
522
549
|
```javascript
|
|
523
|
-
record.
|
|
550
|
+
record.errors.length; // 0
|
|
524
551
|
record.set('foo', 'invalid value');
|
|
525
552
|
record.save().catch(function() {
|
|
526
|
-
record.
|
|
553
|
+
record.errors.foo;
|
|
527
554
|
// [{message: 'foo should be a number.', attribute: 'foo'}]
|
|
528
555
|
});
|
|
529
556
|
```
|
|
@@ -565,22 +592,7 @@ class Model extends EmberObject {
|
|
|
565
592
|
@computeOnce
|
|
566
593
|
get errors() {
|
|
567
594
|
let errors = Errors.create({ __record: this });
|
|
568
|
-
|
|
569
|
-
// with the code managing the update. Probably a
|
|
570
|
-
// lazy flush similar to retrieveLatest in ManyArray
|
|
571
|
-
let recordData = recordDataFor(this);
|
|
572
|
-
let jsonApiErrors;
|
|
573
|
-
if (recordData.getErrors) {
|
|
574
|
-
jsonApiErrors = recordData.getErrors();
|
|
575
|
-
if (jsonApiErrors) {
|
|
576
|
-
let errorsHash = errorsArrayToHash(jsonApiErrors);
|
|
577
|
-
let errorKeys = Object.keys(errorsHash);
|
|
578
|
-
|
|
579
|
-
for (let i = 0; i < errorKeys.length; i++) {
|
|
580
|
-
errors.add(errorKeys[i], errorsHash[errorKeys[i]]);
|
|
581
|
-
}
|
|
582
|
-
}
|
|
583
|
-
}
|
|
595
|
+
this.currentState.updateInvalidErrors(errors);
|
|
584
596
|
return errors;
|
|
585
597
|
}
|
|
586
598
|
|
|
@@ -812,7 +824,7 @@ class Model extends EmberObject {
|
|
|
812
824
|
and value is an [oldProp, newProp] array.
|
|
813
825
|
*/
|
|
814
826
|
changedAttributes() {
|
|
815
|
-
return this.
|
|
827
|
+
return recordDataFor(this).changedAttrs(recordIdentifierFor(this));
|
|
816
828
|
}
|
|
817
829
|
|
|
818
830
|
/**
|
|
@@ -822,11 +834,11 @@ class Model extends EmberObject {
|
|
|
822
834
|
Example
|
|
823
835
|
|
|
824
836
|
```javascript
|
|
825
|
-
record.
|
|
837
|
+
record.name; // 'Untitled Document'
|
|
826
838
|
record.set('name', 'Doc 1');
|
|
827
|
-
record.
|
|
839
|
+
record.name; // 'Doc 1'
|
|
828
840
|
record.rollbackAttributes();
|
|
829
|
-
record.
|
|
841
|
+
record.name; // 'Untitled Document'
|
|
830
842
|
```
|
|
831
843
|
|
|
832
844
|
@since 1.13.0
|
|
@@ -835,8 +847,16 @@ class Model extends EmberObject {
|
|
|
835
847
|
*/
|
|
836
848
|
rollbackAttributes() {
|
|
837
849
|
const { currentState } = this;
|
|
838
|
-
|
|
839
|
-
|
|
850
|
+
const { isNew } = currentState;
|
|
851
|
+
|
|
852
|
+
storeFor(this)._join(() => {
|
|
853
|
+
recordDataFor(this).rollbackAttrs(recordIdentifierFor(this));
|
|
854
|
+
this.errors.clear();
|
|
855
|
+
currentState.cleanErrorRequests();
|
|
856
|
+
if (isNew) {
|
|
857
|
+
this.unloadRecord();
|
|
858
|
+
}
|
|
859
|
+
});
|
|
840
860
|
}
|
|
841
861
|
|
|
842
862
|
/**
|
|
@@ -848,13 +868,6 @@ class Model extends EmberObject {
|
|
|
848
868
|
return storeFor(this)._instanceCache.createSnapshot(recordIdentifierFor(this));
|
|
849
869
|
}
|
|
850
870
|
|
|
851
|
-
toStringExtension() {
|
|
852
|
-
// the _internalModel guard exists, because some dev-only deprecation code
|
|
853
|
-
// (addListener via validatePropertyInjections) invokes toString before the
|
|
854
|
-
// object is real.
|
|
855
|
-
return this._internalModel && this._internalModel.id;
|
|
856
|
-
}
|
|
857
|
-
|
|
858
871
|
/**
|
|
859
872
|
Save the record and persist any changes to the record to an
|
|
860
873
|
external source via the adapter.
|
|
@@ -981,7 +994,7 @@ class Model extends EmberObject {
|
|
|
981
994
|
import Model, { belongsTo } from '@ember-data/model';
|
|
982
995
|
|
|
983
996
|
export default class BlogModel extends Model {
|
|
984
|
-
@belongsTo({ async: true }) user;
|
|
997
|
+
@belongsTo('user', { async: true, inverse: null }) user;
|
|
985
998
|
}
|
|
986
999
|
```
|
|
987
1000
|
|
|
@@ -1037,7 +1050,7 @@ class Model extends EmberObject {
|
|
|
1037
1050
|
@return {BelongsToReference} reference for this relationship
|
|
1038
1051
|
*/
|
|
1039
1052
|
belongsTo(name) {
|
|
1040
|
-
return
|
|
1053
|
+
return lookupLegacySupport(this).referenceFor('belongsTo', name);
|
|
1041
1054
|
}
|
|
1042
1055
|
|
|
1043
1056
|
/**
|
|
@@ -1049,7 +1062,7 @@ class Model extends EmberObject {
|
|
|
1049
1062
|
import Model, { hasMany } from '@ember-data/model';
|
|
1050
1063
|
|
|
1051
1064
|
export default class BlogModel extends Model {
|
|
1052
|
-
@hasMany({ async: true }) comments;
|
|
1065
|
+
@hasMany('comment', { async: true, inverse: null }) comments;
|
|
1053
1066
|
}
|
|
1054
1067
|
|
|
1055
1068
|
let blog = store.push({
|
|
@@ -1100,7 +1113,7 @@ class Model extends EmberObject {
|
|
|
1100
1113
|
@return {HasManyReference} reference for this relationship
|
|
1101
1114
|
*/
|
|
1102
1115
|
hasMany(name) {
|
|
1103
|
-
return
|
|
1116
|
+
return lookupLegacySupport(this).referenceFor('hasMany', name);
|
|
1104
1117
|
}
|
|
1105
1118
|
|
|
1106
1119
|
/**
|
|
@@ -1142,7 +1155,7 @@ class Model extends EmberObject {
|
|
|
1142
1155
|
record.eachRelationship(function(name, descriptor) {
|
|
1143
1156
|
if (descriptor.kind === 'hasMany') {
|
|
1144
1157
|
let serializedHasManyName = name.toUpperCase() + '_IDS';
|
|
1145
|
-
json[serializedHasManyName] = record.get(name).
|
|
1158
|
+
json[serializedHasManyName] = record.get(name).map(r => r.id);
|
|
1146
1159
|
}
|
|
1147
1160
|
});
|
|
1148
1161
|
|
|
@@ -1202,7 +1215,7 @@ class Model extends EmberObject {
|
|
|
1202
1215
|
|
|
1203
1216
|
```javascript
|
|
1204
1217
|
import RESTSerializer from '@ember-data/serializer/rest';
|
|
1205
|
-
import { underscore } from '
|
|
1218
|
+
import { underscore } from '<app-name>/utils/string-utils';
|
|
1206
1219
|
|
|
1207
1220
|
export default const PostSerializer = RESTSerializer.extend({
|
|
1208
1221
|
payloadKeyFromModelName(modelName) {
|
|
@@ -1258,12 +1271,46 @@ class Model extends EmberObject {
|
|
|
1258
1271
|
@return {Model} the type of the relationship, or undefined
|
|
1259
1272
|
*/
|
|
1260
1273
|
static typeForRelationship(name, store) {
|
|
1274
|
+
if (DEPRECATE_EARLY_STATIC) {
|
|
1275
|
+
deprecate(
|
|
1276
|
+
`Accessing schema information on Models without looking up the model via the store is deprecated. Use store.modelFor (or better Snapshots or the store.getSchemaDefinitionService() apis) instead.`,
|
|
1277
|
+
this.modelName,
|
|
1278
|
+
{
|
|
1279
|
+
id: 'ember-data:deprecate-early-static',
|
|
1280
|
+
for: 'ember-data',
|
|
1281
|
+
until: '5.0',
|
|
1282
|
+
since: { available: '4.8', enabled: '4.8' },
|
|
1283
|
+
}
|
|
1284
|
+
);
|
|
1285
|
+
} else {
|
|
1286
|
+
assert(
|
|
1287
|
+
`Accessing schema information on Models without looking up the model via the store is disallowed.`,
|
|
1288
|
+
this.modelName
|
|
1289
|
+
);
|
|
1290
|
+
}
|
|
1261
1291
|
let relationship = this.relationshipsByName.get(name);
|
|
1262
1292
|
return relationship && store.modelFor(relationship.type);
|
|
1263
1293
|
}
|
|
1264
1294
|
|
|
1265
1295
|
@computeOnce
|
|
1266
1296
|
static get inverseMap() {
|
|
1297
|
+
if (DEPRECATE_EARLY_STATIC) {
|
|
1298
|
+
deprecate(
|
|
1299
|
+
`Accessing schema information on Models without looking up the model via the store is deprecated. Use store.modelFor (or better Snapshots or the store.getSchemaDefinitionService() apis) instead.`,
|
|
1300
|
+
this.modelName,
|
|
1301
|
+
{
|
|
1302
|
+
id: 'ember-data:deprecate-early-static',
|
|
1303
|
+
for: 'ember-data',
|
|
1304
|
+
until: '5.0',
|
|
1305
|
+
since: { available: '4.8', enabled: '4.8' },
|
|
1306
|
+
}
|
|
1307
|
+
);
|
|
1308
|
+
} else {
|
|
1309
|
+
assert(
|
|
1310
|
+
`Accessing schema information on Models without looking up the model via the store is disallowed.`,
|
|
1311
|
+
this.modelName
|
|
1312
|
+
);
|
|
1313
|
+
}
|
|
1267
1314
|
return Object.create(null);
|
|
1268
1315
|
}
|
|
1269
1316
|
|
|
@@ -1301,6 +1348,23 @@ class Model extends EmberObject {
|
|
|
1301
1348
|
@return {Object} the inverse relationship, or null
|
|
1302
1349
|
*/
|
|
1303
1350
|
static inverseFor(name, store) {
|
|
1351
|
+
if (DEPRECATE_EARLY_STATIC) {
|
|
1352
|
+
deprecate(
|
|
1353
|
+
`Accessing schema information on Models without looking up the model via the store is deprecated. Use store.modelFor (or better Snapshots or the store.getSchemaDefinitionService() apis) instead.`,
|
|
1354
|
+
this.modelName,
|
|
1355
|
+
{
|
|
1356
|
+
id: 'ember-data:deprecate-early-static',
|
|
1357
|
+
for: 'ember-data',
|
|
1358
|
+
until: '5.0',
|
|
1359
|
+
since: { available: '4.8', enabled: '4.8' },
|
|
1360
|
+
}
|
|
1361
|
+
);
|
|
1362
|
+
} else {
|
|
1363
|
+
assert(
|
|
1364
|
+
`Accessing schema information on Models without looking up the model via the store is disallowed.`,
|
|
1365
|
+
this.modelName
|
|
1366
|
+
);
|
|
1367
|
+
}
|
|
1304
1368
|
let inverseMap = this.inverseMap;
|
|
1305
1369
|
if (inverseMap[name]) {
|
|
1306
1370
|
return inverseMap[name];
|
|
@@ -1313,42 +1377,63 @@ class Model extends EmberObject {
|
|
|
1313
1377
|
|
|
1314
1378
|
//Calculate the inverse, ignoring the cache
|
|
1315
1379
|
static _findInverseFor(name, store) {
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1380
|
+
if (DEPRECATE_EARLY_STATIC) {
|
|
1381
|
+
deprecate(
|
|
1382
|
+
`Accessing schema information on Models without looking up the model via the store is deprecated. Use store.modelFor (or better Snapshots or the store.getSchemaDefinitionService() apis) instead.`,
|
|
1383
|
+
this.modelName,
|
|
1384
|
+
{
|
|
1385
|
+
id: 'ember-data:deprecate-early-static',
|
|
1386
|
+
for: 'ember-data',
|
|
1387
|
+
until: '5.0',
|
|
1388
|
+
since: { available: '4.8', enabled: '4.8' },
|
|
1389
|
+
}
|
|
1390
|
+
);
|
|
1391
|
+
} else {
|
|
1392
|
+
assert(
|
|
1393
|
+
`Accessing schema information on Models without looking up the model via the store is disallowed.`,
|
|
1394
|
+
this.modelName
|
|
1395
|
+
);
|
|
1319
1396
|
}
|
|
1320
1397
|
|
|
1321
|
-
|
|
1398
|
+
const relationship = this.relationshipsByName.get(name);
|
|
1399
|
+
const { options } = relationship;
|
|
1400
|
+
const isPolymorphic = options.polymorphic;
|
|
1401
|
+
|
|
1322
1402
|
//If inverse is manually specified to be null, like `comments: hasMany('message', { inverse: null })`
|
|
1323
|
-
|
|
1324
|
-
|
|
1403
|
+
const isExplicitInverseNull = options.inverse === null;
|
|
1404
|
+
const isAbstractType =
|
|
1405
|
+
!isExplicitInverseNull && isPolymorphic && !store.getSchemaDefinitionService().doesTypeExist(relationship.type);
|
|
1406
|
+
|
|
1407
|
+
if (isExplicitInverseNull || isAbstractType) {
|
|
1408
|
+
assert(
|
|
1409
|
+
`No schema for the abstract type '${relationship.type}' for the polymorphic relationship '${name}' on '${this.modelName}' was provided by the SchemaDefinitionService.`,
|
|
1410
|
+
!isPolymorphic || isExplicitInverseNull
|
|
1411
|
+
);
|
|
1325
1412
|
return null;
|
|
1326
1413
|
}
|
|
1327
1414
|
|
|
1328
|
-
let
|
|
1415
|
+
let fieldOnInverse, inverseKind, inverseRelationship, inverseOptions;
|
|
1416
|
+
let inverseSchema = this.typeForRelationship(name, store);
|
|
1329
1417
|
|
|
1418
|
+
// if the type does not exist and we are not polymorphic
|
|
1330
1419
|
//If inverse is specified manually, return the inverse
|
|
1331
|
-
if (options.inverse) {
|
|
1332
|
-
|
|
1333
|
-
|
|
1420
|
+
if (options.inverse !== undefined) {
|
|
1421
|
+
fieldOnInverse = options.inverse;
|
|
1422
|
+
inverseRelationship = inverseSchema && inverseSchema.relationshipsByName.get(fieldOnInverse);
|
|
1334
1423
|
|
|
1335
1424
|
assert(
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
"' on the '" +
|
|
1339
|
-
inverseType.modelName +
|
|
1340
|
-
"' model. This is most likely due to a missing attribute on your model definition.",
|
|
1341
|
-
!isNone(inverse)
|
|
1425
|
+
`We found no field named '${fieldOnInverse}' on the schema for '${inverseSchema.modelName}' to be the inverse of the '${name}' relationship on '${this.modelName}'. This is most likely due to a missing field on your model definition.`,
|
|
1426
|
+
inverseRelationship
|
|
1342
1427
|
);
|
|
1343
1428
|
|
|
1344
1429
|
// TODO probably just return the whole inverse here
|
|
1345
|
-
inverseKind =
|
|
1346
|
-
inverseOptions =
|
|
1430
|
+
inverseKind = inverseRelationship.kind;
|
|
1431
|
+
inverseOptions = inverseRelationship.options;
|
|
1347
1432
|
} else {
|
|
1348
1433
|
//No inverse was specified manually, we need to use a heuristic to guess one
|
|
1349
|
-
if (
|
|
1434
|
+
if (relationship.type === relationship.parentModelName) {
|
|
1350
1435
|
warn(
|
|
1351
|
-
`Detected a reflexive relationship
|
|
1436
|
+
`Detected a reflexive relationship named '${name}' on the schema for '${relationship.type}' without an inverse option. Look at https://guides.emberjs.com/current/models/relationships/#toc_reflexive-relations for how to explicitly specify inverses.`,
|
|
1352
1437
|
false,
|
|
1353
1438
|
{
|
|
1354
1439
|
id: 'ds.model.reflexive-relationship-without-inverse',
|
|
@@ -1356,30 +1441,33 @@ class Model extends EmberObject {
|
|
|
1356
1441
|
);
|
|
1357
1442
|
}
|
|
1358
1443
|
|
|
1359
|
-
let possibleRelationships = findPossibleInverses(this,
|
|
1444
|
+
let possibleRelationships = findPossibleInverses(this, inverseSchema, name);
|
|
1360
1445
|
|
|
1361
1446
|
if (possibleRelationships.length === 0) {
|
|
1362
1447
|
return null;
|
|
1363
1448
|
}
|
|
1364
1449
|
|
|
1365
|
-
|
|
1366
|
-
let
|
|
1367
|
-
|
|
1368
|
-
|
|
1450
|
+
if (DEBUG) {
|
|
1451
|
+
let filteredRelationships = possibleRelationships.filter((possibleRelationship) => {
|
|
1452
|
+
let optionsForRelationship = possibleRelationship.options;
|
|
1453
|
+
return name === optionsForRelationship.inverse;
|
|
1454
|
+
});
|
|
1369
1455
|
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1456
|
+
assert(
|
|
1457
|
+
"You defined the '" +
|
|
1458
|
+
name +
|
|
1459
|
+
"' relationship on " +
|
|
1460
|
+
this +
|
|
1461
|
+
', but you defined the inverse relationships of type ' +
|
|
1462
|
+
inverseSchema.toString() +
|
|
1463
|
+
' multiple times. Look at https://guides.emberjs.com/current/models/relationships/#toc_explicit-inverses for how to explicitly specify inverses',
|
|
1464
|
+
filteredRelationships.length < 2
|
|
1465
|
+
);
|
|
1466
|
+
}
|
|
1380
1467
|
|
|
1381
|
-
|
|
1382
|
-
|
|
1468
|
+
let explicitRelationship = possibleRelationships.find((relationship) => relationship.options.inverse === name);
|
|
1469
|
+
if (explicitRelationship) {
|
|
1470
|
+
possibleRelationships = [explicitRelationship];
|
|
1383
1471
|
}
|
|
1384
1472
|
|
|
1385
1473
|
assert(
|
|
@@ -1390,24 +1478,78 @@ class Model extends EmberObject {
|
|
|
1390
1478
|
', but multiple possible inverse relationships of type ' +
|
|
1391
1479
|
this +
|
|
1392
1480
|
' were found on ' +
|
|
1393
|
-
|
|
1481
|
+
inverseSchema +
|
|
1394
1482
|
'. Look at https://guides.emberjs.com/current/models/relationships/#toc_explicit-inverses for how to explicitly specify inverses',
|
|
1395
1483
|
possibleRelationships.length === 1
|
|
1396
1484
|
);
|
|
1397
1485
|
|
|
1398
|
-
|
|
1486
|
+
fieldOnInverse = possibleRelationships[0].name;
|
|
1399
1487
|
inverseKind = possibleRelationships[0].kind;
|
|
1400
1488
|
inverseOptions = possibleRelationships[0].options;
|
|
1401
1489
|
}
|
|
1402
1490
|
|
|
1491
|
+
// ensure inverse is properly configured
|
|
1492
|
+
if (DEBUG && isPolymorphic) {
|
|
1493
|
+
if (DEPRECATE_NON_EXPLICIT_POLYMORPHISM) {
|
|
1494
|
+
if (!inverseOptions.as) {
|
|
1495
|
+
deprecate(
|
|
1496
|
+
`Relationships that satisfy polymorphic relationships MUST define which abstract-type they are satisfying using 'as'. The field '${fieldOnInverse}' on type '${inverseSchema.modelName}' is misconfigured.`,
|
|
1497
|
+
false,
|
|
1498
|
+
{
|
|
1499
|
+
id: 'ember-data:non-explicit-relationships',
|
|
1500
|
+
since: { enabled: '4.8', available: '4.8' },
|
|
1501
|
+
until: '5.0',
|
|
1502
|
+
for: 'ember-data',
|
|
1503
|
+
}
|
|
1504
|
+
);
|
|
1505
|
+
}
|
|
1506
|
+
} else {
|
|
1507
|
+
assert(
|
|
1508
|
+
`Relationships that satisfy polymorphic relationships MUST define which abstract-type they are satisfying using 'as'. The field '${fieldOnInverse}' on type '${inverseSchema.modelName}' is misconfigured.`,
|
|
1509
|
+
inverseOptions.as
|
|
1510
|
+
);
|
|
1511
|
+
assert(
|
|
1512
|
+
`options.as should match the expected type of the polymorphic relationship. Expected field '${fieldOnInverse}' on type '${inverseSchema.modelName}' to specify '${relationship.type}' but found '${inverseOptions.as}'`,
|
|
1513
|
+
!!inverseOptions.as && relationship.type === inverseOptions.as
|
|
1514
|
+
);
|
|
1515
|
+
}
|
|
1516
|
+
}
|
|
1517
|
+
|
|
1518
|
+
// ensure we are properly configured
|
|
1519
|
+
if (DEBUG && inverseOptions.polymorphic) {
|
|
1520
|
+
if (DEPRECATE_NON_EXPLICIT_POLYMORPHISM) {
|
|
1521
|
+
if (!options.as) {
|
|
1522
|
+
deprecate(
|
|
1523
|
+
`Relationships that satisfy polymorphic relationships MUST define which abstract-type they are satisfying using 'as'. The field '${name}' on type '${this.modelName}' is misconfigured.`,
|
|
1524
|
+
false,
|
|
1525
|
+
{
|
|
1526
|
+
id: 'ember-data:non-explicit-relationships',
|
|
1527
|
+
since: { enabled: '4.8', available: '4.8' },
|
|
1528
|
+
until: '5.0',
|
|
1529
|
+
for: 'ember-data',
|
|
1530
|
+
}
|
|
1531
|
+
);
|
|
1532
|
+
}
|
|
1533
|
+
} else {
|
|
1534
|
+
assert(
|
|
1535
|
+
`Relationships that satisfy polymorphic relationships MUST define which abstract-type they are satisfying using 'as'. The field '${name}' on type '${this.modelName}' is misconfigured.`,
|
|
1536
|
+
options.as
|
|
1537
|
+
);
|
|
1538
|
+
assert(
|
|
1539
|
+
`options.as should match the expected type of the polymorphic relationship. Expected field '${name}' on type '${this.modelName}' to specify '${inverseRelationship.type}' but found '${options.as}'`,
|
|
1540
|
+
!!options.as && inverseRelationship.type === options.as
|
|
1541
|
+
);
|
|
1542
|
+
}
|
|
1543
|
+
}
|
|
1544
|
+
|
|
1403
1545
|
assert(
|
|
1404
|
-
`The ${
|
|
1405
|
-
|
|
1546
|
+
`The ${inverseSchema.modelName}:${fieldOnInverse} relationship declares 'inverse: null', but it was resolved as the inverse for ${this.modelName}:${name}.`,
|
|
1547
|
+
inverseOptions.inverse !== null
|
|
1406
1548
|
);
|
|
1407
1549
|
|
|
1408
1550
|
return {
|
|
1409
|
-
type:
|
|
1410
|
-
name:
|
|
1551
|
+
type: inverseSchema,
|
|
1552
|
+
name: fieldOnInverse,
|
|
1411
1553
|
kind: inverseKind,
|
|
1412
1554
|
options: inverseOptions,
|
|
1413
1555
|
};
|
|
@@ -1441,10 +1583,10 @@ class Model extends EmberObject {
|
|
|
1441
1583
|
import Post from 'app/models/post';
|
|
1442
1584
|
|
|
1443
1585
|
let relationships = Blog.relationships;
|
|
1444
|
-
relationships.
|
|
1586
|
+
relationships.user;
|
|
1445
1587
|
//=> [ { name: 'users', kind: 'hasMany' },
|
|
1446
1588
|
// { name: 'owner', kind: 'belongsTo' } ]
|
|
1447
|
-
relationships.
|
|
1589
|
+
relationships.post;
|
|
1448
1590
|
//=> [ { name: 'posts', kind: 'hasMany' } ]
|
|
1449
1591
|
```
|
|
1450
1592
|
|
|
@@ -1457,6 +1599,23 @@ class Model extends EmberObject {
|
|
|
1457
1599
|
|
|
1458
1600
|
@computeOnce
|
|
1459
1601
|
static get relationships() {
|
|
1602
|
+
if (DEPRECATE_EARLY_STATIC) {
|
|
1603
|
+
deprecate(
|
|
1604
|
+
`Accessing schema information on Models without looking up the model via the store is deprecated. Use store.modelFor (or better Snapshots or the store.getSchemaDefinitionService() apis) instead.`,
|
|
1605
|
+
this.modelName,
|
|
1606
|
+
{
|
|
1607
|
+
id: 'ember-data:deprecate-early-static',
|
|
1608
|
+
for: 'ember-data',
|
|
1609
|
+
until: '5.0',
|
|
1610
|
+
since: { available: '4.8', enabled: '4.8' },
|
|
1611
|
+
}
|
|
1612
|
+
);
|
|
1613
|
+
} else {
|
|
1614
|
+
assert(
|
|
1615
|
+
`Accessing schema information on Models without looking up the model via the store is disallowed.`,
|
|
1616
|
+
this.modelName
|
|
1617
|
+
);
|
|
1618
|
+
}
|
|
1460
1619
|
let map = new Map();
|
|
1461
1620
|
let relationshipsByName = this.relationshipsByName;
|
|
1462
1621
|
|
|
@@ -1511,6 +1670,23 @@ class Model extends EmberObject {
|
|
|
1511
1670
|
*/
|
|
1512
1671
|
@computeOnce
|
|
1513
1672
|
static get relationshipNames() {
|
|
1673
|
+
if (DEPRECATE_EARLY_STATIC) {
|
|
1674
|
+
deprecate(
|
|
1675
|
+
`Accessing schema information on Models without looking up the model via the store is deprecated. Use store.modelFor (or better Snapshots or the store.getSchemaDefinitionService() apis) instead.`,
|
|
1676
|
+
this.modelName,
|
|
1677
|
+
{
|
|
1678
|
+
id: 'ember-data:deprecate-early-static',
|
|
1679
|
+
for: 'ember-data',
|
|
1680
|
+
until: '5.0',
|
|
1681
|
+
since: { available: '4.8', enabled: '4.8' },
|
|
1682
|
+
}
|
|
1683
|
+
);
|
|
1684
|
+
} else {
|
|
1685
|
+
assert(
|
|
1686
|
+
`Accessing schema information on Models without looking up the model via the store is disallowed.`,
|
|
1687
|
+
this.modelName
|
|
1688
|
+
);
|
|
1689
|
+
}
|
|
1514
1690
|
let names = {
|
|
1515
1691
|
hasMany: [],
|
|
1516
1692
|
belongsTo: [],
|
|
@@ -1561,6 +1737,23 @@ class Model extends EmberObject {
|
|
|
1561
1737
|
*/
|
|
1562
1738
|
@computeOnce
|
|
1563
1739
|
static get relatedTypes() {
|
|
1740
|
+
if (DEPRECATE_EARLY_STATIC) {
|
|
1741
|
+
deprecate(
|
|
1742
|
+
`Accessing schema information on Models without looking up the model via the store is deprecated. Use store.modelFor (or better Snapshots or the store.getSchemaDefinitionService() apis) instead.`,
|
|
1743
|
+
this.modelName,
|
|
1744
|
+
{
|
|
1745
|
+
id: 'ember-data:deprecate-early-static',
|
|
1746
|
+
for: 'ember-data',
|
|
1747
|
+
until: '5.0',
|
|
1748
|
+
since: { available: '4.8', enabled: '4.8' },
|
|
1749
|
+
}
|
|
1750
|
+
);
|
|
1751
|
+
} else {
|
|
1752
|
+
assert(
|
|
1753
|
+
`Accessing schema information on Models without looking up the model via the store is disallowed.`,
|
|
1754
|
+
this.modelName
|
|
1755
|
+
);
|
|
1756
|
+
}
|
|
1564
1757
|
let types = [];
|
|
1565
1758
|
|
|
1566
1759
|
let rels = this.relationshipsObject;
|
|
@@ -1606,9 +1799,9 @@ class Model extends EmberObject {
|
|
|
1606
1799
|
import Blog from 'app/models/blog';
|
|
1607
1800
|
|
|
1608
1801
|
let relationshipsByName = Blog.relationshipsByName;
|
|
1609
|
-
relationshipsByName.
|
|
1802
|
+
relationshipsByName.users;
|
|
1610
1803
|
//=> { key: 'users', kind: 'hasMany', type: 'user', options: Object, isRelationship: true }
|
|
1611
|
-
relationshipsByName.
|
|
1804
|
+
relationshipsByName.owner;
|
|
1612
1805
|
//=> { key: 'owner', kind: 'belongsTo', type: 'user', options: Object, isRelationship: true }
|
|
1613
1806
|
```
|
|
1614
1807
|
|
|
@@ -1620,6 +1813,23 @@ class Model extends EmberObject {
|
|
|
1620
1813
|
*/
|
|
1621
1814
|
@computeOnce
|
|
1622
1815
|
static get relationshipsByName() {
|
|
1816
|
+
if (DEPRECATE_EARLY_STATIC) {
|
|
1817
|
+
deprecate(
|
|
1818
|
+
`Accessing schema information on Models without looking up the model via the store is deprecated. Use store.modelFor (or better Snapshots or the store.getSchemaDefinitionService() apis) instead.`,
|
|
1819
|
+
this.modelName,
|
|
1820
|
+
{
|
|
1821
|
+
id: 'ember-data:deprecate-early-static',
|
|
1822
|
+
for: 'ember-data',
|
|
1823
|
+
until: '5.0',
|
|
1824
|
+
since: { available: '4.8', enabled: '4.8' },
|
|
1825
|
+
}
|
|
1826
|
+
);
|
|
1827
|
+
} else {
|
|
1828
|
+
assert(
|
|
1829
|
+
`Accessing schema information on Models without looking up the model via the store is disallowed.`,
|
|
1830
|
+
this.modelName
|
|
1831
|
+
);
|
|
1832
|
+
}
|
|
1623
1833
|
let map = new Map();
|
|
1624
1834
|
let rels = this.relationshipsObject;
|
|
1625
1835
|
let relationships = Object.keys(rels);
|
|
@@ -1636,6 +1846,23 @@ class Model extends EmberObject {
|
|
|
1636
1846
|
|
|
1637
1847
|
@computeOnce
|
|
1638
1848
|
static get relationshipsObject() {
|
|
1849
|
+
if (DEPRECATE_EARLY_STATIC) {
|
|
1850
|
+
deprecate(
|
|
1851
|
+
`Accessing schema information on Models without looking up the model via the store is deprecated. Use store.modelFor (or better Snapshots or the store.getSchemaDefinitionService() apis) instead.`,
|
|
1852
|
+
this.modelName,
|
|
1853
|
+
{
|
|
1854
|
+
id: 'ember-data:deprecate-early-static',
|
|
1855
|
+
for: 'ember-data',
|
|
1856
|
+
until: '5.0',
|
|
1857
|
+
since: { available: '4.8', enabled: '4.8' },
|
|
1858
|
+
}
|
|
1859
|
+
);
|
|
1860
|
+
} else {
|
|
1861
|
+
assert(
|
|
1862
|
+
`Accessing schema information on Models without looking up the model via the store is disallowed.`,
|
|
1863
|
+
this.modelName
|
|
1864
|
+
);
|
|
1865
|
+
}
|
|
1639
1866
|
let relationships = Object.create(null);
|
|
1640
1867
|
let modelName = this.modelName;
|
|
1641
1868
|
this.eachComputedProperty((name, meta) => {
|
|
@@ -1643,7 +1870,7 @@ class Model extends EmberObject {
|
|
|
1643
1870
|
meta.key = name;
|
|
1644
1871
|
meta.name = name;
|
|
1645
1872
|
meta.parentModelName = modelName;
|
|
1646
|
-
relationships[name] = relationshipFromMeta(meta);
|
|
1873
|
+
relationships[name] = DEPRECATE_RELATIONSHIPS_WITHOUT_INVERSE ? relationshipFromMeta(meta) : meta;
|
|
1647
1874
|
}
|
|
1648
1875
|
});
|
|
1649
1876
|
return relationships;
|
|
@@ -1675,7 +1902,7 @@ class Model extends EmberObject {
|
|
|
1675
1902
|
|
|
1676
1903
|
let fields = Blog.fields;
|
|
1677
1904
|
fields.forEach(function(kind, field) {
|
|
1678
|
-
|
|
1905
|
+
// do thing
|
|
1679
1906
|
});
|
|
1680
1907
|
|
|
1681
1908
|
// prints:
|
|
@@ -1693,9 +1920,27 @@ class Model extends EmberObject {
|
|
|
1693
1920
|
*/
|
|
1694
1921
|
@computeOnce
|
|
1695
1922
|
static get fields() {
|
|
1923
|
+
if (DEPRECATE_EARLY_STATIC) {
|
|
1924
|
+
deprecate(
|
|
1925
|
+
`Accessing schema information on Models without looking up the model via the store is deprecated. Use store.modelFor (or better Snapshots or the store.getSchemaDefinitionService() apis) instead.`,
|
|
1926
|
+
this.modelName,
|
|
1927
|
+
{
|
|
1928
|
+
id: 'ember-data:deprecate-early-static',
|
|
1929
|
+
for: 'ember-data',
|
|
1930
|
+
until: '5.0',
|
|
1931
|
+
since: { available: '4.8', enabled: '4.8' },
|
|
1932
|
+
}
|
|
1933
|
+
);
|
|
1934
|
+
} else {
|
|
1935
|
+
assert(
|
|
1936
|
+
`Accessing schema information on Models without looking up the model via the store is disallowed.`,
|
|
1937
|
+
this.modelName
|
|
1938
|
+
);
|
|
1939
|
+
}
|
|
1696
1940
|
let map = new Map();
|
|
1697
1941
|
|
|
1698
1942
|
this.eachComputedProperty((name, meta) => {
|
|
1943
|
+
// TODO end reliance on these booleans and stop leaking them in the spec
|
|
1699
1944
|
if (meta.isRelationship) {
|
|
1700
1945
|
map.set(name, meta.kind);
|
|
1701
1946
|
} else if (meta.isAttribute) {
|
|
@@ -1718,6 +1963,23 @@ class Model extends EmberObject {
|
|
|
1718
1963
|
@param {any} binding the value to which the callback's `this` should be bound
|
|
1719
1964
|
*/
|
|
1720
1965
|
static eachRelationship(callback, binding) {
|
|
1966
|
+
if (DEPRECATE_EARLY_STATIC) {
|
|
1967
|
+
deprecate(
|
|
1968
|
+
`Accessing schema information on Models without looking up the model via the store is deprecated. Use store.modelFor (or better Snapshots or the store.getSchemaDefinitionService() apis) instead.`,
|
|
1969
|
+
this.modelName,
|
|
1970
|
+
{
|
|
1971
|
+
id: 'ember-data:deprecate-early-static',
|
|
1972
|
+
for: 'ember-data',
|
|
1973
|
+
until: '5.0',
|
|
1974
|
+
since: { available: '4.8', enabled: '4.8' },
|
|
1975
|
+
}
|
|
1976
|
+
);
|
|
1977
|
+
} else {
|
|
1978
|
+
assert(
|
|
1979
|
+
`Accessing schema information on Models without looking up the model via the store is disallowed.`,
|
|
1980
|
+
this.modelName
|
|
1981
|
+
);
|
|
1982
|
+
}
|
|
1721
1983
|
this.relationshipsByName.forEach((relationship, name) => {
|
|
1722
1984
|
callback.call(binding, name, relationship);
|
|
1723
1985
|
});
|
|
@@ -1736,6 +1998,23 @@ class Model extends EmberObject {
|
|
|
1736
1998
|
@param {any} binding the value to which the callback's `this` should be bound
|
|
1737
1999
|
*/
|
|
1738
2000
|
static eachRelatedType(callback, binding) {
|
|
2001
|
+
if (DEPRECATE_EARLY_STATIC) {
|
|
2002
|
+
deprecate(
|
|
2003
|
+
`Accessing schema information on Models without looking up the model via the store is deprecated. Use store.modelFor (or better Snapshots or the store.getSchemaDefinitionService() apis) instead.`,
|
|
2004
|
+
this.modelName,
|
|
2005
|
+
{
|
|
2006
|
+
id: 'ember-data:deprecate-early-static',
|
|
2007
|
+
for: 'ember-data',
|
|
2008
|
+
until: '5.0',
|
|
2009
|
+
since: { available: '4.8', enabled: '4.8' },
|
|
2010
|
+
}
|
|
2011
|
+
);
|
|
2012
|
+
} else {
|
|
2013
|
+
assert(
|
|
2014
|
+
`Accessing schema information on Models without looking up the model via the store is disallowed.`,
|
|
2015
|
+
this.modelName
|
|
2016
|
+
);
|
|
2017
|
+
}
|
|
1739
2018
|
let relationshipTypes = this.relatedTypes;
|
|
1740
2019
|
|
|
1741
2020
|
for (let i = 0; i < relationshipTypes.length; i++) {
|
|
@@ -1745,6 +2024,23 @@ class Model extends EmberObject {
|
|
|
1745
2024
|
}
|
|
1746
2025
|
|
|
1747
2026
|
static determineRelationshipType(knownSide, store) {
|
|
2027
|
+
if (DEPRECATE_EARLY_STATIC) {
|
|
2028
|
+
deprecate(
|
|
2029
|
+
`Accessing schema information on Models without looking up the model via the store is deprecated. Use store.modelFor (or better Snapshots or the store.getSchemaDefinitionService() apis) instead.`,
|
|
2030
|
+
this.modelName,
|
|
2031
|
+
{
|
|
2032
|
+
id: 'ember-data:deprecate-early-static',
|
|
2033
|
+
for: 'ember-data',
|
|
2034
|
+
until: '5.0',
|
|
2035
|
+
since: { available: '4.8', enabled: '4.8' },
|
|
2036
|
+
}
|
|
2037
|
+
);
|
|
2038
|
+
} else {
|
|
2039
|
+
assert(
|
|
2040
|
+
`Accessing schema information on Models without looking up the model via the store is disallowed.`,
|
|
2041
|
+
this.modelName
|
|
2042
|
+
);
|
|
2043
|
+
}
|
|
1748
2044
|
let knownKey = knownSide.key;
|
|
1749
2045
|
let knownKind = knownSide.kind;
|
|
1750
2046
|
let inverse = this.inverseFor(knownKey, store);
|
|
@@ -1789,7 +2085,7 @@ class Model extends EmberObject {
|
|
|
1789
2085
|
let attributes = Person.attributes
|
|
1790
2086
|
|
|
1791
2087
|
attributes.forEach(function(meta, name) {
|
|
1792
|
-
|
|
2088
|
+
// do thing
|
|
1793
2089
|
});
|
|
1794
2090
|
|
|
1795
2091
|
// prints:
|
|
@@ -1806,6 +2102,23 @@ class Model extends EmberObject {
|
|
|
1806
2102
|
*/
|
|
1807
2103
|
@computeOnce
|
|
1808
2104
|
static get attributes() {
|
|
2105
|
+
if (DEPRECATE_EARLY_STATIC) {
|
|
2106
|
+
deprecate(
|
|
2107
|
+
`Accessing schema information on Models without looking up the model via the store is deprecated. Use store.modelFor (or better Snapshots or the store.getSchemaDefinitionService() apis) instead.`,
|
|
2108
|
+
this.modelName,
|
|
2109
|
+
{
|
|
2110
|
+
id: 'ember-data:deprecate-early-static',
|
|
2111
|
+
for: 'ember-data',
|
|
2112
|
+
until: '5.0',
|
|
2113
|
+
since: { available: '4.8', enabled: '4.8' },
|
|
2114
|
+
}
|
|
2115
|
+
);
|
|
2116
|
+
} else {
|
|
2117
|
+
assert(
|
|
2118
|
+
`Accessing schema information on Models without looking up the model via the store is disallowed.`,
|
|
2119
|
+
this.modelName
|
|
2120
|
+
);
|
|
2121
|
+
}
|
|
1809
2122
|
let map = new Map();
|
|
1810
2123
|
|
|
1811
2124
|
this.eachComputedProperty((name, meta) => {
|
|
@@ -1849,7 +2162,7 @@ class Model extends EmberObject {
|
|
|
1849
2162
|
let transformedAttributes = Person.transformedAttributes
|
|
1850
2163
|
|
|
1851
2164
|
transformedAttributes.forEach(function(field, type) {
|
|
1852
|
-
|
|
2165
|
+
// do thing
|
|
1853
2166
|
});
|
|
1854
2167
|
|
|
1855
2168
|
// prints:
|
|
@@ -1865,6 +2178,23 @@ class Model extends EmberObject {
|
|
|
1865
2178
|
*/
|
|
1866
2179
|
@computeOnce
|
|
1867
2180
|
static get transformedAttributes() {
|
|
2181
|
+
if (DEPRECATE_EARLY_STATIC) {
|
|
2182
|
+
deprecate(
|
|
2183
|
+
`Accessing schema information on Models without looking up the model via the store is deprecated. Use store.modelFor (or better Snapshots or the store.getSchemaDefinitionService() apis) instead.`,
|
|
2184
|
+
this.modelName,
|
|
2185
|
+
{
|
|
2186
|
+
id: 'ember-data:deprecate-early-static',
|
|
2187
|
+
for: 'ember-data',
|
|
2188
|
+
until: '5.0',
|
|
2189
|
+
since: { available: '4.8', enabled: '4.8' },
|
|
2190
|
+
}
|
|
2191
|
+
);
|
|
2192
|
+
} else {
|
|
2193
|
+
assert(
|
|
2194
|
+
`Accessing schema information on Models without looking up the model via the store is disallowed.`,
|
|
2195
|
+
this.modelName
|
|
2196
|
+
);
|
|
2197
|
+
}
|
|
1868
2198
|
let map = new Map();
|
|
1869
2199
|
|
|
1870
2200
|
this.eachAttribute((key, meta) => {
|
|
@@ -1905,7 +2235,7 @@ class Model extends EmberObject {
|
|
|
1905
2235
|
}
|
|
1906
2236
|
|
|
1907
2237
|
PersonModel.eachAttribute(function(name, meta) {
|
|
1908
|
-
|
|
2238
|
+
// do thing
|
|
1909
2239
|
});
|
|
1910
2240
|
|
|
1911
2241
|
// prints:
|
|
@@ -1921,6 +2251,23 @@ class Model extends EmberObject {
|
|
|
1921
2251
|
@static
|
|
1922
2252
|
*/
|
|
1923
2253
|
static eachAttribute(callback, binding) {
|
|
2254
|
+
if (DEPRECATE_EARLY_STATIC) {
|
|
2255
|
+
deprecate(
|
|
2256
|
+
`Accessing schema information on Models without looking up the model via the store is deprecated. Use store.modelFor (or better Snapshots or the store.getSchemaDefinitionService() apis) instead.`,
|
|
2257
|
+
this.modelName,
|
|
2258
|
+
{
|
|
2259
|
+
id: 'ember-data:deprecate-early-static',
|
|
2260
|
+
for: 'ember-data',
|
|
2261
|
+
until: '5.0',
|
|
2262
|
+
since: { available: '4.8', enabled: '4.8' },
|
|
2263
|
+
}
|
|
2264
|
+
);
|
|
2265
|
+
} else {
|
|
2266
|
+
assert(
|
|
2267
|
+
`Accessing schema information on Models without looking up the model via the store is disallowed.`,
|
|
2268
|
+
this.modelName
|
|
2269
|
+
);
|
|
2270
|
+
}
|
|
1924
2271
|
this.attributes.forEach((meta, name) => {
|
|
1925
2272
|
callback.call(binding, name, meta);
|
|
1926
2273
|
});
|
|
@@ -1957,7 +2304,7 @@ class Model extends EmberObject {
|
|
|
1957
2304
|
});
|
|
1958
2305
|
|
|
1959
2306
|
Person.eachTransformedAttribute(function(name, type) {
|
|
1960
|
-
|
|
2307
|
+
// do thing
|
|
1961
2308
|
});
|
|
1962
2309
|
|
|
1963
2310
|
// prints:
|
|
@@ -1972,6 +2319,23 @@ class Model extends EmberObject {
|
|
|
1972
2319
|
@static
|
|
1973
2320
|
*/
|
|
1974
2321
|
static eachTransformedAttribute(callback, binding) {
|
|
2322
|
+
if (DEPRECATE_EARLY_STATIC) {
|
|
2323
|
+
deprecate(
|
|
2324
|
+
`Accessing schema information on Models without looking up the model via the store is deprecated. Use store.modelFor (or better Snapshots or the store.getSchemaDefinitionService() apis) instead.`,
|
|
2325
|
+
this.modelName,
|
|
2326
|
+
{
|
|
2327
|
+
id: 'ember-data:deprecate-early-static',
|
|
2328
|
+
for: 'ember-data',
|
|
2329
|
+
until: '5.0',
|
|
2330
|
+
since: { available: '4.8', enabled: '4.8' },
|
|
2331
|
+
}
|
|
2332
|
+
);
|
|
2333
|
+
} else {
|
|
2334
|
+
assert(
|
|
2335
|
+
`Accessing schema information on Models without looking up the model via the store is disallowed.`,
|
|
2336
|
+
this.modelName
|
|
2337
|
+
);
|
|
2338
|
+
}
|
|
1975
2339
|
this.transformedAttributes.forEach((type, name) => {
|
|
1976
2340
|
callback.call(binding, name, type);
|
|
1977
2341
|
});
|
|
@@ -1985,13 +2349,29 @@ class Model extends EmberObject {
|
|
|
1985
2349
|
@static
|
|
1986
2350
|
*/
|
|
1987
2351
|
static toString() {
|
|
1988
|
-
|
|
2352
|
+
if (DEPRECATE_EARLY_STATIC) {
|
|
2353
|
+
deprecate(
|
|
2354
|
+
`Accessing schema information on Models without looking up the model via the store is deprecated. Use store.modelFor (or better Snapshots or the store.getSchemaDefinitionService() apis) instead.`,
|
|
2355
|
+
this.modelName,
|
|
2356
|
+
{
|
|
2357
|
+
id: 'ember-data:deprecate-early-static',
|
|
2358
|
+
for: 'ember-data',
|
|
2359
|
+
until: '5.0',
|
|
2360
|
+
since: { available: '4.8', enabled: '4.8' },
|
|
2361
|
+
}
|
|
2362
|
+
);
|
|
2363
|
+
} else {
|
|
2364
|
+
assert(
|
|
2365
|
+
`Accessing schema information on Models without looking up the model via the store is disallowed.`,
|
|
2366
|
+
this.modelName
|
|
2367
|
+
);
|
|
2368
|
+
}
|
|
2369
|
+
return `model:${this.modelName}`;
|
|
1989
2370
|
}
|
|
1990
2371
|
}
|
|
1991
2372
|
|
|
1992
2373
|
// this is required to prevent `init` from passing
|
|
1993
2374
|
// the values initialized during create to `setUnknownProperty`
|
|
1994
|
-
Model.prototype._internalModel = null;
|
|
1995
2375
|
Model.prototype._createProps = null;
|
|
1996
2376
|
Model.prototype._secretInit = null;
|
|
1997
2377
|
|
|
@@ -2071,27 +2451,11 @@ if (DEBUG) {
|
|
|
2071
2451
|
} while (current !== null);
|
|
2072
2452
|
return null;
|
|
2073
2453
|
};
|
|
2074
|
-
let isBasicDesc = function isBasicDesc(desc) {
|
|
2075
|
-
return (
|
|
2076
|
-
!desc ||
|
|
2077
|
-
(!desc.get && !desc.set && desc.enumerable === true && desc.writable === true && desc.configurable === true)
|
|
2078
|
-
);
|
|
2079
|
-
};
|
|
2080
|
-
let isDefaultEmptyDescriptor = function isDefaultEmptyDescriptor(obj, keyName) {
|
|
2081
|
-
let instanceDesc = lookupDescriptor(obj, keyName);
|
|
2082
|
-
return isBasicDesc(instanceDesc) && lookupDescriptor(obj.constructor, keyName) === null;
|
|
2083
|
-
};
|
|
2084
2454
|
|
|
2085
2455
|
Model.reopen({
|
|
2086
2456
|
init() {
|
|
2087
2457
|
this._super(...arguments);
|
|
2088
2458
|
|
|
2089
|
-
if (!isDefaultEmptyDescriptor(this, '_internalModel') || !(this._internalModel instanceof InternalModel)) {
|
|
2090
|
-
throw new Error(
|
|
2091
|
-
`'_internalModel' is a reserved property name on instances of classes extending Model. Please choose a different property name for ${this.constructor.toString()}`
|
|
2092
|
-
);
|
|
2093
|
-
}
|
|
2094
|
-
|
|
2095
2459
|
let ourDescriptor = lookupDescriptor(Model.prototype, 'currentState');
|
|
2096
2460
|
let theirDescriptor = lookupDescriptor(this, 'currentState');
|
|
2097
2461
|
let realState = this.___recordState;
|
|
@@ -2111,6 +2475,35 @@ if (DEBUG) {
|
|
|
2111
2475
|
}
|
|
2112
2476
|
},
|
|
2113
2477
|
});
|
|
2478
|
+
|
|
2479
|
+
if (DEPRECATE_MODEL_REOPEN) {
|
|
2480
|
+
const originalReopen = Model.reopen;
|
|
2481
|
+
const originalReopenClass = Model.reopenClass;
|
|
2482
|
+
|
|
2483
|
+
Model.reopen = function deprecatedReopen() {
|
|
2484
|
+
deprecate(`Model.reopen is deprecated. Use Foo extends Model to extend your class instead.`, false, {
|
|
2485
|
+
id: 'ember-data:deprecate-model-reopen',
|
|
2486
|
+
for: 'ember-data',
|
|
2487
|
+
until: '5.0',
|
|
2488
|
+
since: { available: '4.8', enabled: '4.8' },
|
|
2489
|
+
});
|
|
2490
|
+
return originalReopen.call(this, ...arguments);
|
|
2491
|
+
};
|
|
2492
|
+
|
|
2493
|
+
Model.reopenClass = function deprecatedReopenClass() {
|
|
2494
|
+
deprecate(
|
|
2495
|
+
`Model.reopenClass is deprecated. Use Foo extends Model to add static methods and properties to your class instead.`,
|
|
2496
|
+
false,
|
|
2497
|
+
{
|
|
2498
|
+
id: 'ember-data:deprecate-model-reopenclass',
|
|
2499
|
+
for: 'ember-data',
|
|
2500
|
+
until: '5.0',
|
|
2501
|
+
since: { available: '4.8', enabled: '4.8' },
|
|
2502
|
+
}
|
|
2503
|
+
);
|
|
2504
|
+
return originalReopenClass.call(this, ...arguments);
|
|
2505
|
+
};
|
|
2506
|
+
}
|
|
2114
2507
|
}
|
|
2115
2508
|
|
|
2116
2509
|
export default Model;
|