@ember-data/model 4.8.0-alpha.1 → 4.8.0-alpha.4

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.
@@ -2,9 +2,9 @@
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, { get } from '@ember/object';
7
+ import EmberObject from '@ember/object';
8
8
  import { dependentKeyCompat } from '@ember/object/compat';
9
9
  import { run } from '@ember/runloop';
10
10
  import { inject as service } from '@ember/service';
@@ -16,16 +16,14 @@ import Ember from 'ember';
16
16
  import { resolve } from 'rsvp';
17
17
 
18
18
  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
19
  import {
22
- coerceId,
23
- deprecatedPromiseObject,
24
- errorsArrayToHash,
25
- InternalModel,
26
- recordDataFor,
27
- WeakCache,
28
- } from '@ember-data/store/-private';
20
+ DEPRECATE_EARLY_STATIC,
21
+ DEPRECATE_MODEL_REOPEN,
22
+ DEPRECATE_RELATIONSHIPS_WITHOUT_INVERSE,
23
+ DEPRECATE_SAVE_PROMISE_ACCESS,
24
+ } from '@ember-data/private-build-infra/deprecations';
25
+ import { recordIdentifierFor, storeFor } from '@ember-data/store';
26
+ import { coerceId, deprecatedPromiseObject, recordDataFor, WeakCache } from '@ember-data/store/-private';
29
27
 
30
28
  import Errors from './errors';
31
29
  import { LegacySupport } from './legacy-relationships-support';
@@ -122,9 +120,10 @@ function computeOnce(target, key, desc) {
122
120
  */
123
121
  class Model extends EmberObject {
124
122
  @service store;
123
+ ___private_notifications;
125
124
 
126
125
  init(options = {}) {
127
- if (DEBUG && !options._secretInit && !options._internalModel && !options._createProps) {
126
+ if (DEBUG && !options._secretInit && !options._createProps) {
128
127
  throw new EmberError(
129
128
  'You should not call `create` on a model. Instead, call `store.createRecord` with the attributes you would like to set.'
130
129
  );
@@ -140,19 +139,29 @@ class Model extends EmberObject {
140
139
 
141
140
  this.setProperties(createProps);
142
141
 
143
- // TODO pass something in such that we don't need internalModel
144
- // to get this info
145
142
  let store = storeFor(this);
146
143
  let notifications = store._notificationManager;
147
144
  let identity = recordIdentifierFor(this);
148
145
 
149
- notifications.subscribe(identity, (identifier, type, key) => {
146
+ this.___private_notifications = notifications.subscribe(identity, (identifier, type, key) => {
150
147
  notifyChanges(identifier, type, key, this, store);
151
148
  });
152
149
  }
153
150
 
154
- willDestroy() {
151
+ destroy() {
155
152
  LEGACY_SUPPORT.get(this)?.destroy();
153
+ this.___recordState?.destroy();
154
+ const store = storeFor(this);
155
+ const identifier = recordIdentifierFor(this);
156
+ store._notificationManager.unsubscribe(this.___private_notifications);
157
+ // Legacy behavior is to notify the relationships on destroy
158
+ // such that they "clear". It's uncertain this behavior would
159
+ // be good for a new model paradigm, likely cheaper and safer
160
+ // to simply not notify, for this reason the store does not itself
161
+ // notify individual changes once the delete has been signaled,
162
+ // this decision is left to model instances.
163
+ notifyChanges(identifier, 'relationships', undefined, this, store);
164
+ super.destroy();
156
165
  }
157
166
 
158
167
  /**
@@ -200,10 +209,10 @@ class Model extends EmberObject {
200
209
 
201
210
  ```javascript
202
211
  let record = store.createRecord('model');
203
- record.get('isLoaded'); // true
212
+ record.isLoaded; // true
204
213
 
205
214
  store.findRecord('model', 1).then(function(model) {
206
- model.get('isLoaded'); // true
215
+ model.isLoaded; // true
207
216
  });
208
217
  ```
209
218
 
@@ -227,12 +236,12 @@ class Model extends EmberObject {
227
236
 
228
237
  ```javascript
229
238
  let record = store.createRecord('model');
230
- record.get('hasDirtyAttributes'); // true
239
+ record.hasDirtyAttributes; // true
231
240
 
232
241
  store.findRecord('model', 1).then(function(model) {
233
- model.get('hasDirtyAttributes'); // false
242
+ model.hasDirtyAttributes; // false
234
243
  model.set('foo', 'some value');
235
- model.get('hasDirtyAttributes'); // true
244
+ model.hasDirtyAttributes; // true
236
245
  });
237
246
  ```
238
247
 
@@ -257,11 +266,11 @@ class Model extends EmberObject {
257
266
 
258
267
  ```javascript
259
268
  let record = store.createRecord('model');
260
- record.get('isSaving'); // false
269
+ record.isSaving; // false
261
270
  let promise = record.save();
262
- record.get('isSaving'); // true
271
+ record.isSaving; // true
263
272
  promise.then(function() {
264
- record.get('isSaving'); // false
273
+ record.isSaving; // false
265
274
  });
266
275
  ```
267
276
 
@@ -287,24 +296,24 @@ class Model extends EmberObject {
287
296
 
288
297
  ```javascript
289
298
  let record = store.createRecord('model');
290
- record.get('isDeleted'); // false
299
+ record.isDeleted; // false
291
300
  record.deleteRecord();
292
301
 
293
302
  // Locally deleted
294
- record.get('isDeleted'); // true
295
- record.get('hasDirtyAttributes'); // true
296
- record.get('isSaving'); // false
303
+ record.isDeleted; // true
304
+ record.hasDirtyAttributes; // true
305
+ record.isSaving; // false
297
306
 
298
307
  // Persisting the deletion
299
308
  let promise = record.save();
300
- record.get('isDeleted'); // true
301
- record.get('isSaving'); // true
309
+ record.isDeleted; // true
310
+ record.isSaving; // true
302
311
 
303
312
  // Deletion Persisted
304
313
  promise.then(function() {
305
- record.get('isDeleted'); // true
306
- record.get('isSaving'); // false
307
- record.get('hasDirtyAttributes'); // false
314
+ record.isDeleted; // true
315
+ record.isSaving; // false
316
+ record.hasDirtyAttributes; // false
308
317
  });
309
318
  ```
310
319
 
@@ -328,10 +337,10 @@ class Model extends EmberObject {
328
337
 
329
338
  ```javascript
330
339
  let record = store.createRecord('model');
331
- record.get('isNew'); // true
340
+ record.isNew; // true
332
341
 
333
342
  record.save().then(function(model) {
334
- model.get('isNew'); // false
343
+ model.isNew; // false
335
344
  });
336
345
  ```
337
346
 
@@ -374,7 +383,7 @@ class Model extends EmberObject {
374
383
 
375
384
  ```javascript
376
385
  let record = store.createRecord('model');
377
- record.get('dirtyType'); // 'created'
386
+ record.dirtyType; // 'created'
378
387
  ```
379
388
 
380
389
  @property dirtyType
@@ -395,10 +404,10 @@ class Model extends EmberObject {
395
404
  Example
396
405
 
397
406
  ```javascript
398
- record.get('isError'); // false
407
+ record.isError; // false
399
408
  record.set('foo', 'valid value');
400
409
  record.save().then(null, function() {
401
- record.get('isError'); // true
410
+ record.isError; // true
402
411
  });
403
412
  ```
404
413
 
@@ -444,10 +453,10 @@ class Model extends EmberObject {
444
453
 
445
454
  ```javascript
446
455
  let record = store.createRecord('model');
447
- record.get('id'); // null
456
+ record.id; // null
448
457
 
449
458
  store.findRecord('model', 1).then(function(model) {
450
- model.get('id'); // '1'
459
+ model.id; // '1'
451
460
  });
452
461
  ```
453
462
 
@@ -457,24 +466,38 @@ class Model extends EmberObject {
457
466
  */
458
467
  @tagged
459
468
  get id() {
460
- // the _internalModel guard exists, because some dev-only deprecation code
469
+ // this guard exists, because some dev-only deprecation code
461
470
  // (addListener via validatePropertyInjections) invokes toString before the
462
471
  // object is real.
463
472
  if (DEBUG) {
464
- if (!this._internalModel) {
473
+ try {
474
+ return recordIdentifierFor(this).id;
475
+ } catch {
465
476
  return void 0;
466
477
  }
467
478
  }
468
- return this._internalModel.id;
479
+ return recordIdentifierFor(this).id;
469
480
  }
470
481
  set id(id) {
471
482
  const normalizedId = coerceId(id);
483
+ const identifier = recordIdentifierFor(this);
484
+ let didChange = normalizedId !== identifier.id;
485
+ assert(
486
+ `Cannot set ${identifier.type} record's id to ${id}, because id is already ${identifier.id}`,
487
+ !didChange || identifier.id === null
488
+ );
472
489
 
473
- if (normalizedId !== null) {
474
- this._internalModel.setId(normalizedId);
490
+ if (normalizedId !== null && didChange) {
491
+ this.store._instanceCache.setRecordId(identifier, normalizedId);
492
+ this.store._notificationManager.notify(identifier, 'identity');
475
493
  }
476
494
  }
477
495
 
496
+ // TODO just write a nice toString
497
+ toStringExtension() {
498
+ return this.id;
499
+ }
500
+
478
501
  /**
479
502
  @property currentState
480
503
  @private
@@ -497,12 +520,6 @@ class Model extends EmberObject {
497
520
  throw new Error('cannot set currentState');
498
521
  }
499
522
 
500
- /**
501
- @property _internalModel
502
- @private
503
- @type {Object}
504
- */
505
-
506
523
  /**
507
524
  The store service instance which created this record instance
508
525
 
@@ -520,10 +537,10 @@ class Model extends EmberObject {
520
537
  - `attribute` The name of the property associated with this error message
521
538
 
522
539
  ```javascript
523
- record.get('errors.length'); // 0
540
+ record.errors.length; // 0
524
541
  record.set('foo', 'invalid value');
525
542
  record.save().catch(function() {
526
- record.get('errors').get('foo');
543
+ record.errors.foo;
527
544
  // [{message: 'foo should be a number.', attribute: 'foo'}]
528
545
  });
529
546
  ```
@@ -565,22 +582,7 @@ class Model extends EmberObject {
565
582
  @computeOnce
566
583
  get errors() {
567
584
  let errors = Errors.create({ __record: this });
568
- // TODO we should unify how errors gets populated
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
- }
585
+ this.currentState.updateInvalidErrors(errors);
584
586
  return errors;
585
587
  }
586
588
 
@@ -812,7 +814,7 @@ class Model extends EmberObject {
812
814
  and value is an [oldProp, newProp] array.
813
815
  */
814
816
  changedAttributes() {
815
- return this._internalModel.changedAttributes();
817
+ return recordDataFor(this).changedAttrs(recordIdentifierFor(this));
816
818
  }
817
819
 
818
820
  /**
@@ -822,11 +824,11 @@ class Model extends EmberObject {
822
824
  Example
823
825
 
824
826
  ```javascript
825
- record.get('name'); // 'Untitled Document'
827
+ record.name; // 'Untitled Document'
826
828
  record.set('name', 'Doc 1');
827
- record.get('name'); // 'Doc 1'
829
+ record.name; // 'Doc 1'
828
830
  record.rollbackAttributes();
829
- record.get('name'); // 'Untitled Document'
831
+ record.name; // 'Untitled Document'
830
832
  ```
831
833
 
832
834
  @since 1.13.0
@@ -835,8 +837,13 @@ class Model extends EmberObject {
835
837
  */
836
838
  rollbackAttributes() {
837
839
  const { currentState } = this;
838
- this._internalModel.rollbackAttributes();
840
+ const { isNew } = currentState;
841
+ recordDataFor(this).rollbackAttrs(recordIdentifierFor(this));
842
+ this.errors.clear();
839
843
  currentState.cleanErrorRequests();
844
+ if (isNew) {
845
+ this.unloadRecord();
846
+ }
840
847
  }
841
848
 
842
849
  /**
@@ -848,13 +855,6 @@ class Model extends EmberObject {
848
855
  return storeFor(this)._instanceCache.createSnapshot(recordIdentifierFor(this));
849
856
  }
850
857
 
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
858
  /**
859
859
  Save the record and persist any changes to the record to an
860
860
  external source via the adapter.
@@ -981,7 +981,7 @@ class Model extends EmberObject {
981
981
  import Model, { belongsTo } from '@ember-data/model';
982
982
 
983
983
  export default class BlogModel extends Model {
984
- @belongsTo({ async: true }) user;
984
+ @belongsTo('user', { async: true, inverse: null }) user;
985
985
  }
986
986
  ```
987
987
 
@@ -1049,7 +1049,7 @@ class Model extends EmberObject {
1049
1049
  import Model, { hasMany } from '@ember-data/model';
1050
1050
 
1051
1051
  export default class BlogModel extends Model {
1052
- @hasMany({ async: true }) comments;
1052
+ @hasMany('comment', { async: true, inverse: null }) comments;
1053
1053
  }
1054
1054
 
1055
1055
  let blog = store.push({
@@ -1202,7 +1202,7 @@ class Model extends EmberObject {
1202
1202
 
1203
1203
  ```javascript
1204
1204
  import RESTSerializer from '@ember-data/serializer/rest';
1205
- import { underscore } from '@ember/string';
1205
+ import { underscore } from '<app-name>/utils/string-utils';
1206
1206
 
1207
1207
  export default const PostSerializer = RESTSerializer.extend({
1208
1208
  payloadKeyFromModelName(modelName) {
@@ -1258,12 +1258,46 @@ class Model extends EmberObject {
1258
1258
  @return {Model} the type of the relationship, or undefined
1259
1259
  */
1260
1260
  static typeForRelationship(name, store) {
1261
+ if (DEPRECATE_EARLY_STATIC) {
1262
+ deprecate(
1263
+ `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.`,
1264
+ this.modelName,
1265
+ {
1266
+ id: 'ember-data:deprecate-early-static',
1267
+ for: 'ember-data',
1268
+ until: '5.0',
1269
+ since: { available: '4.8', enabled: '4.8' },
1270
+ }
1271
+ );
1272
+ } else {
1273
+ assert(
1274
+ `Accessing schema information on Models without looking up the model via the store is disallowed.`,
1275
+ this.modelName
1276
+ );
1277
+ }
1261
1278
  let relationship = this.relationshipsByName.get(name);
1262
1279
  return relationship && store.modelFor(relationship.type);
1263
1280
  }
1264
1281
 
1265
1282
  @computeOnce
1266
1283
  static get inverseMap() {
1284
+ if (DEPRECATE_EARLY_STATIC) {
1285
+ deprecate(
1286
+ `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.`,
1287
+ this.modelName,
1288
+ {
1289
+ id: 'ember-data:deprecate-early-static',
1290
+ for: 'ember-data',
1291
+ until: '5.0',
1292
+ since: { available: '4.8', enabled: '4.8' },
1293
+ }
1294
+ );
1295
+ } else {
1296
+ assert(
1297
+ `Accessing schema information on Models without looking up the model via the store is disallowed.`,
1298
+ this.modelName
1299
+ );
1300
+ }
1267
1301
  return Object.create(null);
1268
1302
  }
1269
1303
 
@@ -1301,6 +1335,23 @@ class Model extends EmberObject {
1301
1335
  @return {Object} the inverse relationship, or null
1302
1336
  */
1303
1337
  static inverseFor(name, store) {
1338
+ if (DEPRECATE_EARLY_STATIC) {
1339
+ deprecate(
1340
+ `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.`,
1341
+ this.modelName,
1342
+ {
1343
+ id: 'ember-data:deprecate-early-static',
1344
+ for: 'ember-data',
1345
+ until: '5.0',
1346
+ since: { available: '4.8', enabled: '4.8' },
1347
+ }
1348
+ );
1349
+ } else {
1350
+ assert(
1351
+ `Accessing schema information on Models without looking up the model via the store is disallowed.`,
1352
+ this.modelName
1353
+ );
1354
+ }
1304
1355
  let inverseMap = this.inverseMap;
1305
1356
  if (inverseMap[name]) {
1306
1357
  return inverseMap[name];
@@ -1313,6 +1364,23 @@ class Model extends EmberObject {
1313
1364
 
1314
1365
  //Calculate the inverse, ignoring the cache
1315
1366
  static _findInverseFor(name, store) {
1367
+ if (DEPRECATE_EARLY_STATIC) {
1368
+ deprecate(
1369
+ `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.`,
1370
+ this.modelName,
1371
+ {
1372
+ id: 'ember-data:deprecate-early-static',
1373
+ for: 'ember-data',
1374
+ until: '5.0',
1375
+ since: { available: '4.8', enabled: '4.8' },
1376
+ }
1377
+ );
1378
+ } else {
1379
+ assert(
1380
+ `Accessing schema information on Models without looking up the model via the store is disallowed.`,
1381
+ this.modelName
1382
+ );
1383
+ }
1316
1384
  let inverseType = this.typeForRelationship(name, store);
1317
1385
  if (!inverseType) {
1318
1386
  return null;
@@ -1441,10 +1509,10 @@ class Model extends EmberObject {
1441
1509
  import Post from 'app/models/post';
1442
1510
 
1443
1511
  let relationships = Blog.relationships;
1444
- relationships.get('user');
1512
+ relationships.user;
1445
1513
  //=> [ { name: 'users', kind: 'hasMany' },
1446
1514
  // { name: 'owner', kind: 'belongsTo' } ]
1447
- relationships.get('post');
1515
+ relationships.post;
1448
1516
  //=> [ { name: 'posts', kind: 'hasMany' } ]
1449
1517
  ```
1450
1518
 
@@ -1457,6 +1525,23 @@ class Model extends EmberObject {
1457
1525
 
1458
1526
  @computeOnce
1459
1527
  static get relationships() {
1528
+ if (DEPRECATE_EARLY_STATIC) {
1529
+ deprecate(
1530
+ `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.`,
1531
+ this.modelName,
1532
+ {
1533
+ id: 'ember-data:deprecate-early-static',
1534
+ for: 'ember-data',
1535
+ until: '5.0',
1536
+ since: { available: '4.8', enabled: '4.8' },
1537
+ }
1538
+ );
1539
+ } else {
1540
+ assert(
1541
+ `Accessing schema information on Models without looking up the model via the store is disallowed.`,
1542
+ this.modelName
1543
+ );
1544
+ }
1460
1545
  let map = new Map();
1461
1546
  let relationshipsByName = this.relationshipsByName;
1462
1547
 
@@ -1511,6 +1596,23 @@ class Model extends EmberObject {
1511
1596
  */
1512
1597
  @computeOnce
1513
1598
  static get relationshipNames() {
1599
+ if (DEPRECATE_EARLY_STATIC) {
1600
+ deprecate(
1601
+ `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.`,
1602
+ this.modelName,
1603
+ {
1604
+ id: 'ember-data:deprecate-early-static',
1605
+ for: 'ember-data',
1606
+ until: '5.0',
1607
+ since: { available: '4.8', enabled: '4.8' },
1608
+ }
1609
+ );
1610
+ } else {
1611
+ assert(
1612
+ `Accessing schema information on Models without looking up the model via the store is disallowed.`,
1613
+ this.modelName
1614
+ );
1615
+ }
1514
1616
  let names = {
1515
1617
  hasMany: [],
1516
1618
  belongsTo: [],
@@ -1561,6 +1663,23 @@ class Model extends EmberObject {
1561
1663
  */
1562
1664
  @computeOnce
1563
1665
  static get relatedTypes() {
1666
+ if (DEPRECATE_EARLY_STATIC) {
1667
+ deprecate(
1668
+ `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.`,
1669
+ this.modelName,
1670
+ {
1671
+ id: 'ember-data:deprecate-early-static',
1672
+ for: 'ember-data',
1673
+ until: '5.0',
1674
+ since: { available: '4.8', enabled: '4.8' },
1675
+ }
1676
+ );
1677
+ } else {
1678
+ assert(
1679
+ `Accessing schema information on Models without looking up the model via the store is disallowed.`,
1680
+ this.modelName
1681
+ );
1682
+ }
1564
1683
  let types = [];
1565
1684
 
1566
1685
  let rels = this.relationshipsObject;
@@ -1606,9 +1725,9 @@ class Model extends EmberObject {
1606
1725
  import Blog from 'app/models/blog';
1607
1726
 
1608
1727
  let relationshipsByName = Blog.relationshipsByName;
1609
- relationshipsByName.get('users');
1728
+ relationshipsByName.users;
1610
1729
  //=> { key: 'users', kind: 'hasMany', type: 'user', options: Object, isRelationship: true }
1611
- relationshipsByName.get('owner');
1730
+ relationshipsByName.owner;
1612
1731
  //=> { key: 'owner', kind: 'belongsTo', type: 'user', options: Object, isRelationship: true }
1613
1732
  ```
1614
1733
 
@@ -1620,6 +1739,23 @@ class Model extends EmberObject {
1620
1739
  */
1621
1740
  @computeOnce
1622
1741
  static get relationshipsByName() {
1742
+ if (DEPRECATE_EARLY_STATIC) {
1743
+ deprecate(
1744
+ `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.`,
1745
+ this.modelName,
1746
+ {
1747
+ id: 'ember-data:deprecate-early-static',
1748
+ for: 'ember-data',
1749
+ until: '5.0',
1750
+ since: { available: '4.8', enabled: '4.8' },
1751
+ }
1752
+ );
1753
+ } else {
1754
+ assert(
1755
+ `Accessing schema information on Models without looking up the model via the store is disallowed.`,
1756
+ this.modelName
1757
+ );
1758
+ }
1623
1759
  let map = new Map();
1624
1760
  let rels = this.relationshipsObject;
1625
1761
  let relationships = Object.keys(rels);
@@ -1636,6 +1772,23 @@ class Model extends EmberObject {
1636
1772
 
1637
1773
  @computeOnce
1638
1774
  static get relationshipsObject() {
1775
+ if (DEPRECATE_EARLY_STATIC) {
1776
+ deprecate(
1777
+ `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.`,
1778
+ this.modelName,
1779
+ {
1780
+ id: 'ember-data:deprecate-early-static',
1781
+ for: 'ember-data',
1782
+ until: '5.0',
1783
+ since: { available: '4.8', enabled: '4.8' },
1784
+ }
1785
+ );
1786
+ } else {
1787
+ assert(
1788
+ `Accessing schema information on Models without looking up the model via the store is disallowed.`,
1789
+ this.modelName
1790
+ );
1791
+ }
1639
1792
  let relationships = Object.create(null);
1640
1793
  let modelName = this.modelName;
1641
1794
  this.eachComputedProperty((name, meta) => {
@@ -1643,7 +1796,7 @@ class Model extends EmberObject {
1643
1796
  meta.key = name;
1644
1797
  meta.name = name;
1645
1798
  meta.parentModelName = modelName;
1646
- relationships[name] = relationshipFromMeta(meta);
1799
+ relationships[name] = DEPRECATE_RELATIONSHIPS_WITHOUT_INVERSE ? relationshipFromMeta(meta) : meta;
1647
1800
  }
1648
1801
  });
1649
1802
  return relationships;
@@ -1675,7 +1828,7 @@ class Model extends EmberObject {
1675
1828
 
1676
1829
  let fields = Blog.fields;
1677
1830
  fields.forEach(function(kind, field) {
1678
- console.log(field, kind);
1831
+ // do thing
1679
1832
  });
1680
1833
 
1681
1834
  // prints:
@@ -1693,9 +1846,27 @@ class Model extends EmberObject {
1693
1846
  */
1694
1847
  @computeOnce
1695
1848
  static get fields() {
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
+ }
1696
1866
  let map = new Map();
1697
1867
 
1698
1868
  this.eachComputedProperty((name, meta) => {
1869
+ // TODO end reliance on these booleans and stop leaking them in the spec
1699
1870
  if (meta.isRelationship) {
1700
1871
  map.set(name, meta.kind);
1701
1872
  } else if (meta.isAttribute) {
@@ -1718,6 +1889,23 @@ class Model extends EmberObject {
1718
1889
  @param {any} binding the value to which the callback's `this` should be bound
1719
1890
  */
1720
1891
  static eachRelationship(callback, binding) {
1892
+ if (DEPRECATE_EARLY_STATIC) {
1893
+ deprecate(
1894
+ `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.`,
1895
+ this.modelName,
1896
+ {
1897
+ id: 'ember-data:deprecate-early-static',
1898
+ for: 'ember-data',
1899
+ until: '5.0',
1900
+ since: { available: '4.8', enabled: '4.8' },
1901
+ }
1902
+ );
1903
+ } else {
1904
+ assert(
1905
+ `Accessing schema information on Models without looking up the model via the store is disallowed.`,
1906
+ this.modelName
1907
+ );
1908
+ }
1721
1909
  this.relationshipsByName.forEach((relationship, name) => {
1722
1910
  callback.call(binding, name, relationship);
1723
1911
  });
@@ -1736,6 +1924,23 @@ class Model extends EmberObject {
1736
1924
  @param {any} binding the value to which the callback's `this` should be bound
1737
1925
  */
1738
1926
  static eachRelatedType(callback, binding) {
1927
+ if (DEPRECATE_EARLY_STATIC) {
1928
+ deprecate(
1929
+ `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.`,
1930
+ this.modelName,
1931
+ {
1932
+ id: 'ember-data:deprecate-early-static',
1933
+ for: 'ember-data',
1934
+ until: '5.0',
1935
+ since: { available: '4.8', enabled: '4.8' },
1936
+ }
1937
+ );
1938
+ } else {
1939
+ assert(
1940
+ `Accessing schema information on Models without looking up the model via the store is disallowed.`,
1941
+ this.modelName
1942
+ );
1943
+ }
1739
1944
  let relationshipTypes = this.relatedTypes;
1740
1945
 
1741
1946
  for (let i = 0; i < relationshipTypes.length; i++) {
@@ -1745,6 +1950,23 @@ class Model extends EmberObject {
1745
1950
  }
1746
1951
 
1747
1952
  static determineRelationshipType(knownSide, store) {
1953
+ if (DEPRECATE_EARLY_STATIC) {
1954
+ deprecate(
1955
+ `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.`,
1956
+ this.modelName,
1957
+ {
1958
+ id: 'ember-data:deprecate-early-static',
1959
+ for: 'ember-data',
1960
+ until: '5.0',
1961
+ since: { available: '4.8', enabled: '4.8' },
1962
+ }
1963
+ );
1964
+ } else {
1965
+ assert(
1966
+ `Accessing schema information on Models without looking up the model via the store is disallowed.`,
1967
+ this.modelName
1968
+ );
1969
+ }
1748
1970
  let knownKey = knownSide.key;
1749
1971
  let knownKind = knownSide.kind;
1750
1972
  let inverse = this.inverseFor(knownKey, store);
@@ -1789,7 +2011,7 @@ class Model extends EmberObject {
1789
2011
  let attributes = Person.attributes
1790
2012
 
1791
2013
  attributes.forEach(function(meta, name) {
1792
- console.log(name, meta);
2014
+ // do thing
1793
2015
  });
1794
2016
 
1795
2017
  // prints:
@@ -1806,6 +2028,23 @@ class Model extends EmberObject {
1806
2028
  */
1807
2029
  @computeOnce
1808
2030
  static get attributes() {
2031
+ if (DEPRECATE_EARLY_STATIC) {
2032
+ deprecate(
2033
+ `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.`,
2034
+ this.modelName,
2035
+ {
2036
+ id: 'ember-data:deprecate-early-static',
2037
+ for: 'ember-data',
2038
+ until: '5.0',
2039
+ since: { available: '4.8', enabled: '4.8' },
2040
+ }
2041
+ );
2042
+ } else {
2043
+ assert(
2044
+ `Accessing schema information on Models without looking up the model via the store is disallowed.`,
2045
+ this.modelName
2046
+ );
2047
+ }
1809
2048
  let map = new Map();
1810
2049
 
1811
2050
  this.eachComputedProperty((name, meta) => {
@@ -1849,7 +2088,7 @@ class Model extends EmberObject {
1849
2088
  let transformedAttributes = Person.transformedAttributes
1850
2089
 
1851
2090
  transformedAttributes.forEach(function(field, type) {
1852
- console.log(field, type);
2091
+ // do thing
1853
2092
  });
1854
2093
 
1855
2094
  // prints:
@@ -1865,6 +2104,23 @@ class Model extends EmberObject {
1865
2104
  */
1866
2105
  @computeOnce
1867
2106
  static get transformedAttributes() {
2107
+ if (DEPRECATE_EARLY_STATIC) {
2108
+ deprecate(
2109
+ `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.`,
2110
+ this.modelName,
2111
+ {
2112
+ id: 'ember-data:deprecate-early-static',
2113
+ for: 'ember-data',
2114
+ until: '5.0',
2115
+ since: { available: '4.8', enabled: '4.8' },
2116
+ }
2117
+ );
2118
+ } else {
2119
+ assert(
2120
+ `Accessing schema information on Models without looking up the model via the store is disallowed.`,
2121
+ this.modelName
2122
+ );
2123
+ }
1868
2124
  let map = new Map();
1869
2125
 
1870
2126
  this.eachAttribute((key, meta) => {
@@ -1905,7 +2161,7 @@ class Model extends EmberObject {
1905
2161
  }
1906
2162
 
1907
2163
  PersonModel.eachAttribute(function(name, meta) {
1908
- console.log(name, meta);
2164
+ // do thing
1909
2165
  });
1910
2166
 
1911
2167
  // prints:
@@ -1921,6 +2177,23 @@ class Model extends EmberObject {
1921
2177
  @static
1922
2178
  */
1923
2179
  static eachAttribute(callback, binding) {
2180
+ if (DEPRECATE_EARLY_STATIC) {
2181
+ deprecate(
2182
+ `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.`,
2183
+ this.modelName,
2184
+ {
2185
+ id: 'ember-data:deprecate-early-static',
2186
+ for: 'ember-data',
2187
+ until: '5.0',
2188
+ since: { available: '4.8', enabled: '4.8' },
2189
+ }
2190
+ );
2191
+ } else {
2192
+ assert(
2193
+ `Accessing schema information on Models without looking up the model via the store is disallowed.`,
2194
+ this.modelName
2195
+ );
2196
+ }
1924
2197
  this.attributes.forEach((meta, name) => {
1925
2198
  callback.call(binding, name, meta);
1926
2199
  });
@@ -1957,7 +2230,7 @@ class Model extends EmberObject {
1957
2230
  });
1958
2231
 
1959
2232
  Person.eachTransformedAttribute(function(name, type) {
1960
- console.log(name, type);
2233
+ // do thing
1961
2234
  });
1962
2235
 
1963
2236
  // prints:
@@ -1972,6 +2245,23 @@ class Model extends EmberObject {
1972
2245
  @static
1973
2246
  */
1974
2247
  static eachTransformedAttribute(callback, binding) {
2248
+ if (DEPRECATE_EARLY_STATIC) {
2249
+ deprecate(
2250
+ `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.`,
2251
+ this.modelName,
2252
+ {
2253
+ id: 'ember-data:deprecate-early-static',
2254
+ for: 'ember-data',
2255
+ until: '5.0',
2256
+ since: { available: '4.8', enabled: '4.8' },
2257
+ }
2258
+ );
2259
+ } else {
2260
+ assert(
2261
+ `Accessing schema information on Models without looking up the model via the store is disallowed.`,
2262
+ this.modelName
2263
+ );
2264
+ }
1975
2265
  this.transformedAttributes.forEach((type, name) => {
1976
2266
  callback.call(binding, name, type);
1977
2267
  });
@@ -1985,13 +2275,29 @@ class Model extends EmberObject {
1985
2275
  @static
1986
2276
  */
1987
2277
  static toString() {
1988
- return `model:${get(this, 'modelName')}`;
2278
+ if (DEPRECATE_EARLY_STATIC) {
2279
+ deprecate(
2280
+ `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.`,
2281
+ this.modelName,
2282
+ {
2283
+ id: 'ember-data:deprecate-early-static',
2284
+ for: 'ember-data',
2285
+ until: '5.0',
2286
+ since: { available: '4.8', enabled: '4.8' },
2287
+ }
2288
+ );
2289
+ } else {
2290
+ assert(
2291
+ `Accessing schema information on Models without looking up the model via the store is disallowed.`,
2292
+ this.modelName
2293
+ );
2294
+ }
2295
+ return `model:${this.modelName}`;
1989
2296
  }
1990
2297
  }
1991
2298
 
1992
2299
  // this is required to prevent `init` from passing
1993
2300
  // the values initialized during create to `setUnknownProperty`
1994
- Model.prototype._internalModel = null;
1995
2301
  Model.prototype._createProps = null;
1996
2302
  Model.prototype._secretInit = null;
1997
2303
 
@@ -2071,27 +2377,11 @@ if (DEBUG) {
2071
2377
  } while (current !== null);
2072
2378
  return null;
2073
2379
  };
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
2380
 
2085
2381
  Model.reopen({
2086
2382
  init() {
2087
2383
  this._super(...arguments);
2088
2384
 
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
2385
  let ourDescriptor = lookupDescriptor(Model.prototype, 'currentState');
2096
2386
  let theirDescriptor = lookupDescriptor(this, 'currentState');
2097
2387
  let realState = this.___recordState;
@@ -2111,6 +2401,35 @@ if (DEBUG) {
2111
2401
  }
2112
2402
  },
2113
2403
  });
2404
+
2405
+ if (DEPRECATE_MODEL_REOPEN) {
2406
+ const originalReopen = Model.reopen;
2407
+ const originalReopenClass = Model.reopenClass;
2408
+
2409
+ Model.reopen = function deprecatedReopen() {
2410
+ deprecate(`Model.reopen is deprecated. Use Foo extends Model to extend your class instead.`, false, {
2411
+ id: 'ember-data:deprecate-model-reopen',
2412
+ for: 'ember-data',
2413
+ until: '5.0',
2414
+ since: { available: '4.8', enabled: '4.8' },
2415
+ });
2416
+ return originalReopen.call(this, ...arguments);
2417
+ };
2418
+
2419
+ Model.reopenClass = function deprecatedReopenClass() {
2420
+ deprecate(
2421
+ `Model.reopenClass is deprecated. Use Foo extends Model to add static methods and properties to your class instead.`,
2422
+ false,
2423
+ {
2424
+ id: 'ember-data:deprecate-model-reopenclass',
2425
+ for: 'ember-data',
2426
+ until: '5.0',
2427
+ since: { available: '4.8', enabled: '4.8' },
2428
+ }
2429
+ );
2430
+ return originalReopenClass.call(this, ...arguments);
2431
+ };
2432
+ }
2114
2433
  }
2115
2434
 
2116
2435
  export default Model;