@ember-data/model 5.3.0-alpha.4 → 5.3.0-alpha.6
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.js +2 -37
- package/addon/-private.js.map +1 -1
- package/addon/has-many-435cd213.js +496 -0
- package/addon/has-many-435cd213.js.map +1 -0
- package/addon/hooks-f9d9fb4f.js +157 -0
- package/addon/hooks-f9d9fb4f.js.map +1 -0
- package/addon/hooks.js +1 -0
- package/addon/hooks.js.map +1 -0
- package/addon/index.js +3 -1
- package/addon/index.js.map +1 -1
- package/addon/{has-many-2baf73c0.js → model-99cdd629.js} +32 -515
- package/addon/model-99cdd629.js.map +1 -0
- package/package.json +9 -9
- package/addon/has-many-2baf73c0.js.map +0 -1
|
@@ -1,15 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { dasherize } from '@ember/string';
|
|
2
2
|
import { assert, warn } from '@ember/debug';
|
|
3
3
|
import EmberObject, { computed, get } from '@ember/object';
|
|
4
|
-
import { recordIdentifierFor, storeFor as storeFor$1 } from '@ember-data/store';
|
|
5
|
-
import { peekCache, RecordArray, MUTATE, SOURCE, recordIdentifierFor as recordIdentifierFor$1, IDENTIFIER_ARRAY_TAG, notifyArray, isStableIdentifier, storeFor, fastPush, coerceId } from '@ember-data/store/-private';
|
|
6
|
-
import { dasherize } from '@ember/string';
|
|
7
|
-
import { A } from '@ember/array';
|
|
8
|
-
import { singularize } from 'ember-inflector';
|
|
9
4
|
import { dependentKeyCompat } from '@ember/object/compat';
|
|
10
5
|
import { run } from '@ember/runloop';
|
|
11
6
|
import { cached, tracked } from '@glimmer/tracking';
|
|
12
7
|
import Ember from 'ember';
|
|
8
|
+
import { macroCondition, getOwnConfig, importSync } from '@embroider/macros';
|
|
9
|
+
import { recordIdentifierFor as recordIdentifierFor$1, storeFor as storeFor$1 } from '@ember-data/store';
|
|
10
|
+
import { RecordArray, MUTATE, SOURCE, recordIdentifierFor, IDENTIFIER_ARRAY_TAG, notifyArray, isStableIdentifier, storeFor, peekCache, fastPush, coerceId } from '@ember-data/store/-private';
|
|
11
|
+
import { A } from '@ember/array';
|
|
13
12
|
import ArrayProxy from '@ember/array/proxy';
|
|
14
13
|
import { mapBy, not } from '@ember/object/computed';
|
|
15
14
|
import PromiseProxyMixin from '@ember/object/promise-proxy-mixin';
|
|
@@ -34,152 +33,9 @@ function isElementDescriptor(args) {
|
|
|
34
33
|
function computedMacroWithOptionalParams(fn) {
|
|
35
34
|
return (...maybeDesc) => isElementDescriptor(maybeDesc) ? fn()(...maybeDesc) : fn(...maybeDesc);
|
|
36
35
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
@module @ember-data/model
|
|
40
|
-
*/
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
`attr` defines an attribute on a [Model](/ember-data/release/classes/Model).
|
|
44
|
-
By default, attributes are passed through as-is, however you can specify an
|
|
45
|
-
optional type to have the value automatically transformed.
|
|
46
|
-
Ember Data ships with four basic transform types: `string`, `number`,
|
|
47
|
-
`boolean` and `date`. You can define your own transforms by subclassing
|
|
48
|
-
[Transform](/ember-data/release/classes/Transform).
|
|
49
|
-
|
|
50
|
-
Note that you cannot use `attr` to define an attribute of `id`.
|
|
51
|
-
|
|
52
|
-
`attr` takes an optional hash as a second parameter, currently
|
|
53
|
-
supported options are:
|
|
54
|
-
|
|
55
|
-
- `defaultValue`: Pass a string or a function to be called to set the attribute
|
|
56
|
-
to a default value if and only if the key is absent from the payload response.
|
|
57
|
-
|
|
58
|
-
Example
|
|
59
|
-
|
|
60
|
-
```app/models/user.js
|
|
61
|
-
import Model, { attr } from '@ember-data/model';
|
|
62
|
-
|
|
63
|
-
export default class UserModel extends Model {
|
|
64
|
-
@attr('string') username;
|
|
65
|
-
@attr('string') email;
|
|
66
|
-
@attr('boolean', { defaultValue: false }) verified;
|
|
67
|
-
}
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
Default value can also be a function. This is useful it you want to return
|
|
71
|
-
a new object for each attribute.
|
|
72
|
-
|
|
73
|
-
```app/models/user.js
|
|
74
|
-
import Model, { attr } from '@ember-data/model';
|
|
75
|
-
|
|
76
|
-
export default class UserModel extends Model {
|
|
77
|
-
@attr('string') username;
|
|
78
|
-
@attr('string') email;
|
|
79
|
-
|
|
80
|
-
@attr({
|
|
81
|
-
defaultValue() {
|
|
82
|
-
return {};
|
|
83
|
-
}
|
|
84
|
-
})
|
|
85
|
-
settings;
|
|
86
|
-
}
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
The `options` hash is passed as second argument to a transforms'
|
|
90
|
-
`serialize` and `deserialize` method. This allows to configure a
|
|
91
|
-
transformation and adapt the corresponding value, based on the config:
|
|
92
|
-
|
|
93
|
-
```app/models/post.js
|
|
94
|
-
import Model, { attr } from '@ember-data/model';
|
|
95
|
-
|
|
96
|
-
export default class PostModel extends Model {
|
|
97
|
-
@attr('text', {
|
|
98
|
-
uppercase: true
|
|
99
|
-
})
|
|
100
|
-
text;
|
|
101
|
-
}
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
```app/transforms/text.js
|
|
105
|
-
export default class TextTransform {
|
|
106
|
-
serialize(value, options) {
|
|
107
|
-
if (options.uppercase) {
|
|
108
|
-
return value.toUpperCase();
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
return value;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
deserialize(value) {
|
|
115
|
-
return value;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
static create() {
|
|
119
|
-
return new this();
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
@method attr
|
|
125
|
-
@public
|
|
126
|
-
@static
|
|
127
|
-
@for @ember-data/model
|
|
128
|
-
@param {String|Object} type the attribute type
|
|
129
|
-
@param {Object} options a hash of options
|
|
130
|
-
@return {Attribute}
|
|
131
|
-
*/
|
|
132
|
-
function attr(type, options) {
|
|
133
|
-
if (typeof type === 'object') {
|
|
134
|
-
options = type;
|
|
135
|
-
type = undefined;
|
|
136
|
-
} else {
|
|
137
|
-
options = options || {};
|
|
138
|
-
}
|
|
139
|
-
let meta = {
|
|
140
|
-
type: type,
|
|
141
|
-
isAttribute: true,
|
|
142
|
-
options: options
|
|
143
|
-
};
|
|
144
|
-
return computed({
|
|
145
|
-
get(key) {
|
|
146
|
-
if (macroCondition(getOwnConfig().env.DEBUG)) {
|
|
147
|
-
if (['currentState'].indexOf(key) !== -1) {
|
|
148
|
-
throw new Error(`'${key}' is a reserved property name on instances of classes extending Model. Please choose a different property name for your attr on ${this.constructor.toString()}`);
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
if (this.isDestroyed || this.isDestroying) {
|
|
152
|
-
return;
|
|
153
|
-
}
|
|
154
|
-
return peekCache(this).getAttr(recordIdentifierFor(this), key);
|
|
155
|
-
},
|
|
156
|
-
set(key, value) {
|
|
157
|
-
if (macroCondition(getOwnConfig().env.DEBUG)) {
|
|
158
|
-
if (['currentState'].indexOf(key) !== -1) {
|
|
159
|
-
throw new Error(`'${key}' is a reserved property name on instances of classes extending Model. Please choose a different property name for your attr on ${this.constructor.toString()}`);
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
assert(`Attempted to set '${key}' on the deleted record ${recordIdentifierFor(this)}`, !this.currentState.isDeleted);
|
|
163
|
-
const identifier = recordIdentifierFor(this);
|
|
164
|
-
const cache = peekCache(this);
|
|
165
|
-
let currentValue = cache.getAttr(identifier, key);
|
|
166
|
-
if (currentValue !== value) {
|
|
167
|
-
cache.setAttr(identifier, key, value);
|
|
168
|
-
if (!this.isValid) {
|
|
169
|
-
const {
|
|
170
|
-
errors
|
|
171
|
-
} = this;
|
|
172
|
-
if (errors.get(key)) {
|
|
173
|
-
errors.remove(key);
|
|
174
|
-
this.currentState.cleanErrorRequests();
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
return value;
|
|
179
|
-
}
|
|
180
|
-
}).meta(meta);
|
|
36
|
+
function normalizeModelName(modelName) {
|
|
37
|
+
return dasherize(modelName);
|
|
181
38
|
}
|
|
182
|
-
var attr$1 = computedMacroWithOptionalParams(attr);
|
|
183
39
|
function _initializerDefineProperty(target, property, descriptor, context) {
|
|
184
40
|
if (!descriptor) return;
|
|
185
41
|
Object.defineProperty(target, property, {
|
|
@@ -728,7 +584,7 @@ class RelatedCollection extends RecordArray {
|
|
|
728
584
|
op: 'removeFromRelatedRecords',
|
|
729
585
|
record: this.identifier,
|
|
730
586
|
field: this.key,
|
|
731
|
-
value: recordIdentifierFor
|
|
587
|
+
value: recordIdentifierFor(result)
|
|
732
588
|
});
|
|
733
589
|
}
|
|
734
590
|
break;
|
|
@@ -747,7 +603,7 @@ class RelatedCollection extends RecordArray {
|
|
|
747
603
|
op: 'removeFromRelatedRecords',
|
|
748
604
|
record: this.identifier,
|
|
749
605
|
field: this.key,
|
|
750
|
-
value: recordIdentifierFor
|
|
606
|
+
value: recordIdentifierFor(result),
|
|
751
607
|
index: 0
|
|
752
608
|
});
|
|
753
609
|
}
|
|
@@ -757,7 +613,7 @@ class RelatedCollection extends RecordArray {
|
|
|
757
613
|
op: 'sortRelatedRecords',
|
|
758
614
|
record: this.identifier,
|
|
759
615
|
field: this.key,
|
|
760
|
-
value: result.map(recordIdentifierFor
|
|
616
|
+
value: result.map(recordIdentifierFor)
|
|
761
617
|
});
|
|
762
618
|
break;
|
|
763
619
|
case 'splice':
|
|
@@ -778,7 +634,7 @@ class RelatedCollection extends RecordArray {
|
|
|
778
634
|
op: 'removeFromRelatedRecords',
|
|
779
635
|
record: this.identifier,
|
|
780
636
|
field: this.key,
|
|
781
|
-
value: result.map(recordIdentifierFor
|
|
637
|
+
value: result.map(recordIdentifierFor),
|
|
782
638
|
index: start
|
|
783
639
|
});
|
|
784
640
|
}
|
|
@@ -869,7 +725,7 @@ RelatedCollection.prototype.DEPRECATED_CLASS_NAME = 'ManyArray';
|
|
|
869
725
|
function assertRecordPassedToHasMany(record) {
|
|
870
726
|
assert(`All elements of a hasMany relationship must be instances of Model, you passed $${typeof record}`, function () {
|
|
871
727
|
try {
|
|
872
|
-
recordIdentifierFor
|
|
728
|
+
recordIdentifierFor(record);
|
|
873
729
|
return true;
|
|
874
730
|
} catch {
|
|
875
731
|
return false;
|
|
@@ -881,7 +737,7 @@ function extractIdentifiersFromRecords(records) {
|
|
|
881
737
|
}
|
|
882
738
|
function extractIdentifierFromRecord$1(recordOrPromiseRecord) {
|
|
883
739
|
assertRecordPassedToHasMany(recordOrPromiseRecord);
|
|
884
|
-
return recordIdentifierFor
|
|
740
|
+
return recordIdentifierFor(recordOrPromiseRecord);
|
|
885
741
|
}
|
|
886
742
|
const PromiseObject = ObjectProxy.extend(PromiseProxyMixin);
|
|
887
743
|
var _dec, _class$5;
|
|
@@ -1511,7 +1367,7 @@ let BelongsToReference = (_class$3 = class BelongsToReference {
|
|
|
1511
1367
|
let record = this.store.push(jsonApiDoc);
|
|
1512
1368
|
if (macroCondition(getOwnConfig().env.DEBUG)) {
|
|
1513
1369
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
|
1514
|
-
assertPolymorphicType(this.belongsToRelationship.identifier, this.belongsToRelationship.definition, recordIdentifierFor
|
|
1370
|
+
assertPolymorphicType(this.belongsToRelationship.identifier, this.belongsToRelationship.definition, recordIdentifierFor(record), this.store);
|
|
1515
1371
|
}
|
|
1516
1372
|
const {
|
|
1517
1373
|
identifier
|
|
@@ -1521,7 +1377,7 @@ let BelongsToReference = (_class$3 = class BelongsToReference {
|
|
|
1521
1377
|
op: 'replaceRelatedRecord',
|
|
1522
1378
|
record: identifier,
|
|
1523
1379
|
field: this.key,
|
|
1524
|
-
value: recordIdentifierFor
|
|
1380
|
+
value: recordIdentifierFor(record)
|
|
1525
1381
|
});
|
|
1526
1382
|
});
|
|
1527
1383
|
return Promise.resolve(record);
|
|
@@ -2008,9 +1864,9 @@ let HasManyReference = (_class$2 = class HasManyReference {
|
|
|
2008
1864
|
let identifier = this.hasManyRelationship.identifier;
|
|
2009
1865
|
|
|
2010
1866
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
|
2011
|
-
assertPolymorphicType(identifier, relationshipMeta, recordIdentifierFor(record), store);
|
|
1867
|
+
assertPolymorphicType(identifier, relationshipMeta, recordIdentifierFor$1(record), store);
|
|
2012
1868
|
}
|
|
2013
|
-
return recordIdentifierFor(record);
|
|
1869
|
+
return recordIdentifierFor$1(record);
|
|
2014
1870
|
});
|
|
2015
1871
|
const {
|
|
2016
1872
|
identifier
|
|
@@ -2197,7 +2053,7 @@ class LegacySupport {
|
|
|
2197
2053
|
constructor(record) {
|
|
2198
2054
|
this.record = record;
|
|
2199
2055
|
this.store = storeFor(record);
|
|
2200
|
-
this.identifier = recordIdentifierFor
|
|
2056
|
+
this.identifier = recordIdentifierFor(record);
|
|
2201
2057
|
this.cache = peekCache(record);
|
|
2202
2058
|
this._manyArrayCache = Object.create(null);
|
|
2203
2059
|
this._relationshipPromisesCache = Object.create(null);
|
|
@@ -2697,7 +2553,7 @@ function extractIdentifierFromRecord(record) {
|
|
|
2697
2553
|
if (!record) {
|
|
2698
2554
|
return null;
|
|
2699
2555
|
}
|
|
2700
|
-
return recordIdentifierFor
|
|
2556
|
+
return recordIdentifierFor(record);
|
|
2701
2557
|
}
|
|
2702
2558
|
function anyUnloaded(store, relationship) {
|
|
2703
2559
|
let state = relationship.localState;
|
|
@@ -2917,7 +2773,7 @@ let RecordState = (_class3 = class RecordState {
|
|
|
2917
2773
|
constructor(record) {
|
|
2918
2774
|
_initializerDefineProperty(this, "isSaving", _descriptor2, this);
|
|
2919
2775
|
const store = storeFor$1(record);
|
|
2920
|
-
const identity = recordIdentifierFor
|
|
2776
|
+
const identity = recordIdentifierFor(record);
|
|
2921
2777
|
this.identifier = identity;
|
|
2922
2778
|
this.record = record;
|
|
2923
2779
|
this.cache = store.cache;
|
|
@@ -3188,7 +3044,7 @@ const {
|
|
|
3188
3044
|
} = Ember;
|
|
3189
3045
|
const LEGACY_SUPPORT = new Map();
|
|
3190
3046
|
function lookupLegacySupport(record) {
|
|
3191
|
-
const identifier = recordIdentifierFor(record);
|
|
3047
|
+
const identifier = recordIdentifierFor$1(record);
|
|
3192
3048
|
let support = LEGACY_SUPPORT.get(identifier);
|
|
3193
3049
|
if (!support) {
|
|
3194
3050
|
assert(`Memory Leak Detected`, !record.isDestroyed && !record.isDestroying);
|
|
@@ -3305,7 +3161,7 @@ let Model = (_class = (_class2 = class Model extends EmberObject {
|
|
|
3305
3161
|
});
|
|
3306
3162
|
}
|
|
3307
3163
|
destroy() {
|
|
3308
|
-
const identifier = recordIdentifierFor(this);
|
|
3164
|
+
const identifier = recordIdentifierFor$1(this);
|
|
3309
3165
|
this.___recordState?.destroy();
|
|
3310
3166
|
const store = storeFor$1(this);
|
|
3311
3167
|
store.notifications.unsubscribe(this.___private_notifications);
|
|
@@ -3569,16 +3425,16 @@ let Model = (_class = (_class2 = class Model extends EmberObject {
|
|
|
3569
3425
|
// object is real.
|
|
3570
3426
|
if (macroCondition(getOwnConfig().env.DEBUG)) {
|
|
3571
3427
|
try {
|
|
3572
|
-
return recordIdentifierFor(this).id;
|
|
3428
|
+
return recordIdentifierFor$1(this).id;
|
|
3573
3429
|
} catch {
|
|
3574
3430
|
return void 0;
|
|
3575
3431
|
}
|
|
3576
3432
|
}
|
|
3577
|
-
return recordIdentifierFor(this).id;
|
|
3433
|
+
return recordIdentifierFor$1(this).id;
|
|
3578
3434
|
}
|
|
3579
3435
|
set id(id) {
|
|
3580
3436
|
const normalizedId = coerceId(id);
|
|
3581
|
-
const identifier = recordIdentifierFor(this);
|
|
3437
|
+
const identifier = recordIdentifierFor$1(this);
|
|
3582
3438
|
let didChange = normalizedId !== identifier.id;
|
|
3583
3439
|
assert(`Cannot set ${identifier.type} record's id to ${id}, because id is already ${identifier.id}`, !didChange || identifier.id === null);
|
|
3584
3440
|
if (normalizedId !== null && didChange) {
|
|
@@ -3870,7 +3726,7 @@ let Model = (_class = (_class2 = class Model extends EmberObject {
|
|
|
3870
3726
|
and value is an [oldProp, newProp] array.
|
|
3871
3727
|
*/
|
|
3872
3728
|
changedAttributes() {
|
|
3873
|
-
return peekCache(this).changedAttrs(recordIdentifierFor(this));
|
|
3729
|
+
return peekCache(this).changedAttrs(recordIdentifierFor$1(this));
|
|
3874
3730
|
}
|
|
3875
3731
|
|
|
3876
3732
|
/**
|
|
@@ -3896,7 +3752,7 @@ let Model = (_class = (_class2 = class Model extends EmberObject {
|
|
|
3896
3752
|
isNew
|
|
3897
3753
|
} = currentState;
|
|
3898
3754
|
storeFor$1(this)._join(() => {
|
|
3899
|
-
peekCache(this).rollbackAttrs(recordIdentifierFor(this));
|
|
3755
|
+
peekCache(this).rollbackAttrs(recordIdentifierFor$1(this));
|
|
3900
3756
|
this.errors.clear();
|
|
3901
3757
|
currentState.cleanErrorRequests();
|
|
3902
3758
|
if (isNew) {
|
|
@@ -3916,7 +3772,7 @@ let Model = (_class = (_class2 = class Model extends EmberObject {
|
|
|
3916
3772
|
const FetchManager = importSync('@ember-data/legacy-compat/-private').FetchManager;
|
|
3917
3773
|
store._fetchManager = new FetchManager(store);
|
|
3918
3774
|
}
|
|
3919
|
-
return store._fetchManager.createSnapshot(recordIdentifierFor(this));
|
|
3775
|
+
return store._fetchManager.createSnapshot(recordIdentifierFor$1(this));
|
|
3920
3776
|
}
|
|
3921
3777
|
|
|
3922
3778
|
/**
|
|
@@ -3958,6 +3814,7 @@ let Model = (_class = (_class2 = class Model extends EmberObject {
|
|
|
3958
3814
|
if (this.currentState.isNew && this.currentState.isDeleted) {
|
|
3959
3815
|
promise = Promise.resolve(this);
|
|
3960
3816
|
} else {
|
|
3817
|
+
this.errors.clear();
|
|
3961
3818
|
promise = storeFor$1(this).saveRecord(this, options);
|
|
3962
3819
|
}
|
|
3963
3820
|
return promise;
|
|
@@ -3989,7 +3846,7 @@ let Model = (_class = (_class2 = class Model extends EmberObject {
|
|
|
3989
3846
|
reload(options = {}) {
|
|
3990
3847
|
options.isReloading = true;
|
|
3991
3848
|
options.reload = true;
|
|
3992
|
-
const identifier = recordIdentifierFor(this);
|
|
3849
|
+
const identifier = recordIdentifierFor$1(this);
|
|
3993
3850
|
assert(`You cannot reload a record without an ID`, identifier.id);
|
|
3994
3851
|
this.isReloading = true;
|
|
3995
3852
|
const promise = storeFor$1(this).request({
|
|
@@ -4837,7 +4694,7 @@ if (macroCondition(getOwnConfig().includeDataAdapter)) {
|
|
|
4837
4694
|
Model.prototype._debugInfo = function () {
|
|
4838
4695
|
let relationships = {};
|
|
4839
4696
|
let expensiveProperties = [];
|
|
4840
|
-
const identifier = recordIdentifierFor(this);
|
|
4697
|
+
const identifier = recordIdentifierFor$1(this);
|
|
4841
4698
|
const schema = this.store.getSchemaDefinitionService();
|
|
4842
4699
|
const attrDefs = schema.attributesDefinitionFor(identifier);
|
|
4843
4700
|
const relDefs = schema.relationshipsDefinitionFor(identifier);
|
|
@@ -4912,344 +4769,4 @@ if (macroCondition(getOwnConfig().env.DEBUG)) {
|
|
|
4912
4769
|
assert(`Model.reopenClass is deprecated. Use Foo extends Model to add static methods and properties to your class instead.`);
|
|
4913
4770
|
};
|
|
4914
4771
|
}
|
|
4915
|
-
|
|
4916
|
-
return dasherize(type);
|
|
4917
|
-
}
|
|
4918
|
-
/**
|
|
4919
|
-
@module @ember-data/model
|
|
4920
|
-
*/
|
|
4921
|
-
|
|
4922
|
-
/**
|
|
4923
|
-
`belongsTo` is used to define One-To-One and One-To-Many
|
|
4924
|
-
relationships on a [Model](/ember-data/release/classes/Model).
|
|
4925
|
-
|
|
4926
|
-
|
|
4927
|
-
`belongsTo` takes an optional hash as a second parameter, currently
|
|
4928
|
-
supported options are:
|
|
4929
|
-
|
|
4930
|
-
- `async`: A boolean value used to explicitly declare this to be an async relationship. The default is true.
|
|
4931
|
-
- `inverse`: A string used to identify the inverse property on a
|
|
4932
|
-
related model in a One-To-Many relationship. See [Explicit Inverses](#explicit-inverses)
|
|
4933
|
-
- `polymorphic` A boolean value to mark the relationship as polymorphic
|
|
4934
|
-
|
|
4935
|
-
#### One-To-One
|
|
4936
|
-
To declare a one-to-one relationship between two models, use
|
|
4937
|
-
`belongsTo`:
|
|
4938
|
-
|
|
4939
|
-
```app/models/user.js
|
|
4940
|
-
import Model, { belongsTo } from '@ember-data/model';
|
|
4941
|
-
|
|
4942
|
-
export default class UserModel extends Model {
|
|
4943
|
-
@belongsTo('profile') profile;
|
|
4944
|
-
}
|
|
4945
|
-
```
|
|
4946
|
-
|
|
4947
|
-
```app/models/profile.js
|
|
4948
|
-
import Model, { belongsTo } from '@ember-data/model';
|
|
4949
|
-
|
|
4950
|
-
export default class ProfileModel extends Model {
|
|
4951
|
-
@belongsTo('user') user;
|
|
4952
|
-
}
|
|
4953
|
-
```
|
|
4954
|
-
|
|
4955
|
-
#### One-To-Many
|
|
4956
|
-
|
|
4957
|
-
To declare a one-to-many relationship between two models, use
|
|
4958
|
-
`belongsTo` in combination with `hasMany`, like this:
|
|
4959
|
-
|
|
4960
|
-
```app/models/post.js
|
|
4961
|
-
import Model, { hasMany } from '@ember-data/model';
|
|
4962
|
-
|
|
4963
|
-
export default class PostModel extends Model {
|
|
4964
|
-
@hasMany('comment', { async: false, inverse: 'post' }) comments;
|
|
4965
|
-
}
|
|
4966
|
-
```
|
|
4967
|
-
|
|
4968
|
-
```app/models/comment.js
|
|
4969
|
-
import Model, { belongsTo } from '@ember-data/model';
|
|
4970
|
-
|
|
4971
|
-
export default class CommentModel extends Model {
|
|
4972
|
-
@belongsTo('post', { async: false, inverse: 'comments' }) post;
|
|
4973
|
-
}
|
|
4974
|
-
```
|
|
4975
|
-
|
|
4976
|
-
#### Sync relationships
|
|
4977
|
-
|
|
4978
|
-
Ember Data resolves sync relationships with the related resources
|
|
4979
|
-
available in its local store, hence it is expected these resources
|
|
4980
|
-
to be loaded before or along-side the primary resource.
|
|
4981
|
-
|
|
4982
|
-
```app/models/comment.js
|
|
4983
|
-
import Model, { belongsTo } from '@ember-data/model';
|
|
4984
|
-
|
|
4985
|
-
export default class CommentModel extends Model {
|
|
4986
|
-
@belongsTo('post', {
|
|
4987
|
-
async: false,
|
|
4988
|
-
inverse: null
|
|
4989
|
-
})
|
|
4990
|
-
post;
|
|
4991
|
-
}
|
|
4992
|
-
```
|
|
4993
|
-
|
|
4994
|
-
In contrast to async relationship, accessing a sync relationship
|
|
4995
|
-
will always return the record (Model instance) for the existing
|
|
4996
|
-
local resource, or null. But it will error on access when
|
|
4997
|
-
a related resource is known to exist and it has not been loaded.
|
|
4998
|
-
|
|
4999
|
-
```
|
|
5000
|
-
let post = comment.post;
|
|
5001
|
-
|
|
5002
|
-
```
|
|
5003
|
-
|
|
5004
|
-
@method belongsTo
|
|
5005
|
-
@public
|
|
5006
|
-
@static
|
|
5007
|
-
@for @ember-data/model
|
|
5008
|
-
@param {String} modelName (optional) type of the relationship
|
|
5009
|
-
@param {Object} options (optional) a hash of options
|
|
5010
|
-
@return {Ember.computed} relationship
|
|
5011
|
-
*/
|
|
5012
|
-
function belongsTo(modelName, options) {
|
|
5013
|
-
let opts = options;
|
|
5014
|
-
let userEnteredModelName = modelName;
|
|
5015
|
-
assert(`Expected belongsTo options.async to be a boolean`, opts && typeof opts.async === 'boolean');
|
|
5016
|
-
assert(`Expected belongsTo options.inverse to be either null or the string type of the related resource.`, opts.inverse === null || typeof opts.inverse === 'string' && opts.inverse.length > 0);
|
|
5017
|
-
let meta = {
|
|
5018
|
-
type: normalizeType$1(userEnteredModelName),
|
|
5019
|
-
isRelationship: true,
|
|
5020
|
-
options: opts,
|
|
5021
|
-
kind: 'belongsTo',
|
|
5022
|
-
name: 'Belongs To',
|
|
5023
|
-
key: null
|
|
5024
|
-
};
|
|
5025
|
-
return computed({
|
|
5026
|
-
get(key) {
|
|
5027
|
-
// this is a legacy behavior we may not carry into a new model setup
|
|
5028
|
-
// it's better to error on disconnected records so users find errors
|
|
5029
|
-
// in their logic.
|
|
5030
|
-
if (this.isDestroying || this.isDestroyed) {
|
|
5031
|
-
return null;
|
|
5032
|
-
}
|
|
5033
|
-
const support = lookupLegacySupport(this);
|
|
5034
|
-
if (macroCondition(getOwnConfig().env.DEBUG)) {
|
|
5035
|
-
if (['currentState'].indexOf(key) !== -1) {
|
|
5036
|
-
throw new Error(`'${key}' is a reserved property name on instances of classes extending Model. Please choose a different property name for your belongsTo on ${this.constructor.toString()}`);
|
|
5037
|
-
}
|
|
5038
|
-
if (Object.prototype.hasOwnProperty.call(opts, 'serialize')) {
|
|
5039
|
-
warn(`You provided a serialize option on the "${key}" property in the "${support.identifier.type}" class, this belongs in the serializer. See Serializer and it's implementations https://api.emberjs.com/ember-data/release/classes/Serializer`, false, {
|
|
5040
|
-
id: 'ds.model.serialize-option-in-belongs-to'
|
|
5041
|
-
});
|
|
5042
|
-
}
|
|
5043
|
-
if (Object.prototype.hasOwnProperty.call(opts, 'embedded')) {
|
|
5044
|
-
warn(`You provided an embedded option on the "${key}" property in the "${support.identifier.type}" class, this belongs in the serializer. See EmbeddedRecordsMixin https://api.emberjs.com/ember-data/release/classes/EmbeddedRecordsMixin`, false, {
|
|
5045
|
-
id: 'ds.model.embedded-option-in-belongs-to'
|
|
5046
|
-
});
|
|
5047
|
-
}
|
|
5048
|
-
}
|
|
5049
|
-
return support.getBelongsTo(key);
|
|
5050
|
-
},
|
|
5051
|
-
set(key, value) {
|
|
5052
|
-
const support = lookupLegacySupport(this);
|
|
5053
|
-
if (macroCondition(getOwnConfig().env.DEBUG)) {
|
|
5054
|
-
if (['currentState'].indexOf(key) !== -1) {
|
|
5055
|
-
throw new Error(`'${key}' is a reserved property name on instances of classes extending Model. Please choose a different property name for your belongsTo on ${this.constructor.toString()}`);
|
|
5056
|
-
}
|
|
5057
|
-
}
|
|
5058
|
-
this.store._join(() => {
|
|
5059
|
-
support.setDirtyBelongsTo(key, value);
|
|
5060
|
-
});
|
|
5061
|
-
return support.getBelongsTo(key);
|
|
5062
|
-
}
|
|
5063
|
-
}).meta(meta);
|
|
5064
|
-
}
|
|
5065
|
-
var belongsTo$1 = computedMacroWithOptionalParams(belongsTo);
|
|
5066
|
-
function normalizeType(type) {
|
|
5067
|
-
return singularize(dasherize(type));
|
|
5068
|
-
}
|
|
5069
|
-
|
|
5070
|
-
/**
|
|
5071
|
-
`hasMany` is used to define One-To-Many and Many-To-Many
|
|
5072
|
-
relationships on a [Model](/ember-data/release/classes/Model).
|
|
5073
|
-
|
|
5074
|
-
`hasMany` takes an optional hash as a second parameter, currently
|
|
5075
|
-
supported options are:
|
|
5076
|
-
|
|
5077
|
-
- `async`: A boolean value used to explicitly declare this to be an async relationship. The default is true.
|
|
5078
|
-
- `inverse`: A string used to identify the inverse property on a related model.
|
|
5079
|
-
- `polymorphic` A boolean value to mark the relationship as polymorphic
|
|
5080
|
-
|
|
5081
|
-
#### One-To-Many
|
|
5082
|
-
To declare a one-to-many relationship between two models, use
|
|
5083
|
-
`belongsTo` in combination with `hasMany`, like this:
|
|
5084
|
-
|
|
5085
|
-
```app/models/post.js
|
|
5086
|
-
import Model, { hasMany } from '@ember-data/model';
|
|
5087
|
-
|
|
5088
|
-
export default class PostModel extends Model {
|
|
5089
|
-
@hasMany('comment') comments;
|
|
5090
|
-
}
|
|
5091
|
-
```
|
|
5092
|
-
|
|
5093
|
-
```app/models/comment.js
|
|
5094
|
-
import Model, { belongsTo } from '@ember-data/model';
|
|
5095
|
-
|
|
5096
|
-
export default class CommentModel extends Model {
|
|
5097
|
-
@belongsTo('post') post;
|
|
5098
|
-
}
|
|
5099
|
-
```
|
|
5100
|
-
|
|
5101
|
-
#### Many-To-Many
|
|
5102
|
-
To declare a many-to-many relationship between two models, use
|
|
5103
|
-
`hasMany`:
|
|
5104
|
-
|
|
5105
|
-
```app/models/post.js
|
|
5106
|
-
import Model, { hasMany } from '@ember-data/model';
|
|
5107
|
-
|
|
5108
|
-
export default class PostModel extends Model {
|
|
5109
|
-
@hasMany('tag') tags;
|
|
5110
|
-
}
|
|
5111
|
-
```
|
|
5112
|
-
|
|
5113
|
-
```app/models/tag.js
|
|
5114
|
-
import Model, { hasMany } from '@ember-data/model';
|
|
5115
|
-
|
|
5116
|
-
export default class TagModel extends Model {
|
|
5117
|
-
@hasMany('post') posts;
|
|
5118
|
-
}
|
|
5119
|
-
```
|
|
5120
|
-
|
|
5121
|
-
You can avoid passing a string as the first parameter. In that case Ember Data
|
|
5122
|
-
will infer the type from the singularized key name.
|
|
5123
|
-
|
|
5124
|
-
```app/models/post.js
|
|
5125
|
-
import Model, { hasMany } from '@ember-data/model';
|
|
5126
|
-
|
|
5127
|
-
export default class PostModel extends Model {
|
|
5128
|
-
@hasMany tags;
|
|
5129
|
-
}
|
|
5130
|
-
```
|
|
5131
|
-
|
|
5132
|
-
will lookup for a Tag type.
|
|
5133
|
-
|
|
5134
|
-
#### Explicit Inverses
|
|
5135
|
-
|
|
5136
|
-
Ember Data will do its best to discover which relationships map to
|
|
5137
|
-
one another. In the one-to-many code above, for example, Ember Data
|
|
5138
|
-
can figure out that changing the `comments` relationship should update
|
|
5139
|
-
the `post` relationship on the inverse because post is the only
|
|
5140
|
-
relationship to that model.
|
|
5141
|
-
|
|
5142
|
-
However, sometimes you may have multiple `belongsTo`/`hasMany` for the
|
|
5143
|
-
same type. You can specify which property on the related model is
|
|
5144
|
-
the inverse using `hasMany`'s `inverse` option:
|
|
5145
|
-
|
|
5146
|
-
```app/models/comment.js
|
|
5147
|
-
import Model, { belongsTo } from '@ember-data/model';
|
|
5148
|
-
|
|
5149
|
-
export default class CommentModel extends Model {
|
|
5150
|
-
@belongsTo('post') onePost;
|
|
5151
|
-
@belongsTo('post') twoPost
|
|
5152
|
-
@belongsTo('post') redPost;
|
|
5153
|
-
@belongsTo('post') bluePost;
|
|
5154
|
-
}
|
|
5155
|
-
```
|
|
5156
|
-
|
|
5157
|
-
```app/models/post.js
|
|
5158
|
-
import Model, { hasMany } from '@ember-data/model';
|
|
5159
|
-
|
|
5160
|
-
export default class PostModel extends Model {
|
|
5161
|
-
@hasMany('comment', {
|
|
5162
|
-
inverse: 'redPost'
|
|
5163
|
-
})
|
|
5164
|
-
comments;
|
|
5165
|
-
}
|
|
5166
|
-
```
|
|
5167
|
-
|
|
5168
|
-
You can also specify an inverse on a `belongsTo`, which works how
|
|
5169
|
-
you'd expect.
|
|
5170
|
-
|
|
5171
|
-
#### Sync relationships
|
|
5172
|
-
|
|
5173
|
-
Ember Data resolves sync relationships with the related resources
|
|
5174
|
-
available in its local store, hence it is expected these resources
|
|
5175
|
-
to be loaded before or along-side the primary resource.
|
|
5176
|
-
|
|
5177
|
-
```app/models/post.js
|
|
5178
|
-
import Model, { hasMany } from '@ember-data/model';
|
|
5179
|
-
|
|
5180
|
-
export default class PostModel extends Model {
|
|
5181
|
-
@hasMany('comment', {
|
|
5182
|
-
async: false
|
|
5183
|
-
})
|
|
5184
|
-
comments;
|
|
5185
|
-
}
|
|
5186
|
-
```
|
|
5187
|
-
|
|
5188
|
-
In contrast to async relationship, accessing a sync relationship
|
|
5189
|
-
will always return a [ManyArray](/ember-data/release/classes/ManyArray) instance
|
|
5190
|
-
containing the existing local resources. But it will error on access
|
|
5191
|
-
when any of the known related resources have not been loaded.
|
|
5192
|
-
|
|
5193
|
-
```
|
|
5194
|
-
post.comments.forEach((comment) => {
|
|
5195
|
-
|
|
5196
|
-
});
|
|
5197
|
-
|
|
5198
|
-
```
|
|
5199
|
-
|
|
5200
|
-
If you are using `links` with sync relationships, you have to use
|
|
5201
|
-
`ref.reload` to fetch the resources.
|
|
5202
|
-
|
|
5203
|
-
@method hasMany
|
|
5204
|
-
@public
|
|
5205
|
-
@static
|
|
5206
|
-
@for @ember-data/model
|
|
5207
|
-
@param {String} type (optional) type of the relationship
|
|
5208
|
-
@param {Object} options (optional) a hash of options
|
|
5209
|
-
@return {Ember.computed} relationship
|
|
5210
|
-
*/
|
|
5211
|
-
function hasMany(type, options) {
|
|
5212
|
-
assert(`Expected hasMany options.async to be a boolean`, options && typeof options.async === 'boolean');
|
|
5213
|
-
|
|
5214
|
-
// Metadata about relationships is stored on the meta of
|
|
5215
|
-
// the relationship. This is used for introspection and
|
|
5216
|
-
// serialization. Note that `key` is populated lazily
|
|
5217
|
-
// the first time the CP is called.
|
|
5218
|
-
let meta = {
|
|
5219
|
-
type: normalizeType(type),
|
|
5220
|
-
options,
|
|
5221
|
-
isRelationship: true,
|
|
5222
|
-
kind: 'hasMany',
|
|
5223
|
-
name: 'Has Many',
|
|
5224
|
-
key: null
|
|
5225
|
-
};
|
|
5226
|
-
return computed({
|
|
5227
|
-
get(key) {
|
|
5228
|
-
if (macroCondition(getOwnConfig().env.DEBUG)) {
|
|
5229
|
-
if (['currentState'].indexOf(key) !== -1) {
|
|
5230
|
-
throw new Error(`'${key}' is a reserved property name on instances of classes extending Model. Please choose a different property name for your hasMany on ${this.constructor.toString()}`);
|
|
5231
|
-
}
|
|
5232
|
-
}
|
|
5233
|
-
if (this.isDestroying || this.isDestroyed) {
|
|
5234
|
-
return A();
|
|
5235
|
-
}
|
|
5236
|
-
return lookupLegacySupport(this).getHasMany(key);
|
|
5237
|
-
},
|
|
5238
|
-
set(key, records) {
|
|
5239
|
-
if (macroCondition(getOwnConfig().env.DEBUG)) {
|
|
5240
|
-
if (['currentState'].indexOf(key) !== -1) {
|
|
5241
|
-
throw new Error(`'${key}' is a reserved property name on instances of classes extending Model. Please choose a different property name for your hasMany on ${this.constructor.toString()}`);
|
|
5242
|
-
}
|
|
5243
|
-
}
|
|
5244
|
-
const support = lookupLegacySupport(this);
|
|
5245
|
-
const manyArray = support.getManyArray(key);
|
|
5246
|
-
assert(`You must pass an array of records to set a hasMany relationship`, Array.isArray(records));
|
|
5247
|
-
this.store._join(() => {
|
|
5248
|
-
manyArray.splice(0, manyArray.length, ...records);
|
|
5249
|
-
});
|
|
5250
|
-
return support.getHasMany(key);
|
|
5251
|
-
}
|
|
5252
|
-
}).meta(meta);
|
|
5253
|
-
}
|
|
5254
|
-
var hasMany$1 = computedMacroWithOptionalParams(hasMany);
|
|
5255
|
-
export { Errors as E, LEGACY_SUPPORT as L, Model as M, PromiseBelongsTo as P, RelatedCollection as R, attr$1 as a, belongsTo$1 as b, PromiseManyArray as c, hasMany$1 as h };
|
|
4772
|
+
export { Errors as E, LEGACY_SUPPORT as L, Model as M, PromiseBelongsTo as P, RelatedCollection as R, PromiseManyArray as a, computedMacroWithOptionalParams as c, lookupLegacySupport as l, normalizeModelName as n };
|