@ember-data/serializer 4.10.0-alpha.2 → 4.10.0-alpha.21
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 +210 -0
- package/addon/-private.js.map +1 -0
- package/addon/{-private/embedded-records-mixin.js → embedded-records-mixin-0a9e9148.js} +87 -146
- package/addon/embedded-records-mixin-0a9e9148.js.map +1 -0
- package/addon/index.js +178 -0
- package/addon/index.js.map +1 -0
- package/addon/json-api.js +96 -233
- package/addon/json-api.js.map +1 -0
- package/addon/json.js +198 -432
- package/addon/json.js.map +1 -0
- package/addon/rest.js +133 -270
- package/addon/rest.js.map +1 -0
- package/addon/{-private/transforms/transform.js → transform-63fba437.js} +9 -15
- package/addon/transform-63fba437.js.map +1 -0
- package/addon/transform.js +3 -4
- package/addon/transform.js.map +1 -0
- package/addon-main.js +90 -0
- package/package.json +39 -8
- package/addon/-private/index.js +0 -11
- package/addon/-private/transforms/boolean.js +0 -70
- package/addon/-private/transforms/date.js +0 -59
- package/addon/-private/transforms/number.js +0 -57
- package/addon/-private/transforms/string.js +0 -38
- package/addon/index.ts +0 -259
- package/blueprints/serializer/files/__root__/__path__/__name__.js +0 -4
- package/blueprints/serializer/index.js +0 -14
- package/blueprints/serializer/native-files/__root__/__path__/__name__.js +0 -4
- package/blueprints/serializer-test/index.js +0 -29
- package/blueprints/serializer-test/mocha-files/__root__/__path__/__test__.js +0 -20
- package/blueprints/serializer-test/mocha-rfc-232-files/__root__/__path__/__test__.js +0 -25
- package/blueprints/serializer-test/qunit-files/__root__/__path__/__test__.js +0 -24
- package/blueprints/transform/files/__root__/__path__/__name__.js +0 -11
- package/blueprints/transform/index.js +0 -7
- package/blueprints/transform/native-files/__root__/__path__/__name__.js +0 -11
- package/blueprints/transform-test/index.js +0 -29
- package/blueprints/transform-test/mocha-files/__root__/__path__/__test__.js +0 -17
- package/blueprints/transform-test/mocha-rfc-232-files/__root__/__path__/__test__.js +0 -14
- package/blueprints/transform-test/qunit-files/__root__/__path__/__test__.js +0 -13
- package/index.js +0 -25
package/addon/rest.js
CHANGED
|
@@ -1,16 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
* @module @ember-data/serializer/rest
|
|
3
|
-
*/
|
|
1
|
+
import { macroCondition, isDevelopingApp } from '@embroider/macros';
|
|
4
2
|
import { assert, warn } from '@ember/debug';
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { DEBUG } from '@glimmer/env';
|
|
8
|
-
|
|
3
|
+
import { dasherize, camelize } from '@ember/string';
|
|
4
|
+
import { typeOf, isNone } from '@ember/utils';
|
|
9
5
|
import { singularize } from 'ember-inflector';
|
|
10
|
-
|
|
11
|
-
import JSONSerializer from '@ember-data/serializer/json';
|
|
12
6
|
import { coerceId } from '@ember-data/store/-private';
|
|
13
|
-
|
|
7
|
+
import JSONSerializer from "./json";
|
|
8
|
+
export { e as EmbeddedRecordsMixin } from "./embedded-records-mixin-0a9e9148";
|
|
14
9
|
function makeArray(value) {
|
|
15
10
|
return Array.isArray(value) ? value : [value];
|
|
16
11
|
}
|
|
@@ -64,22 +59,17 @@ const RESTSerializer = JSONSerializer.extend({
|
|
|
64
59
|
`keyForPolymorphicType` can be used to define a custom key when
|
|
65
60
|
serializing and deserializing a polymorphic type. By default, the
|
|
66
61
|
returned key is `${key}Type`.
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
```app/serializers/post.js
|
|
62
|
+
Example
|
|
63
|
+
```app/serializers/post.js
|
|
71
64
|
import RESTSerializer from '@ember-data/serializer/rest';
|
|
72
|
-
|
|
73
|
-
export default class ApplicationSerializer extends RESTSerializer {
|
|
65
|
+
export default class ApplicationSerializer extends RESTSerializer {
|
|
74
66
|
keyForPolymorphicType(key, relationship) {
|
|
75
67
|
let relationshipKey = this.keyForRelationship(key);
|
|
76
|
-
|
|
77
|
-
return 'type-' + relationshipKey;
|
|
68
|
+
return 'type-' + relationshipKey;
|
|
78
69
|
}
|
|
79
70
|
}
|
|
80
71
|
```
|
|
81
|
-
|
|
82
|
-
@method keyForPolymorphicType
|
|
72
|
+
@method keyForPolymorphicType
|
|
83
73
|
@public
|
|
84
74
|
@param {String} key
|
|
85
75
|
@param {String} typeClass
|
|
@@ -88,22 +78,17 @@ const RESTSerializer = JSONSerializer.extend({
|
|
|
88
78
|
*/
|
|
89
79
|
keyForPolymorphicType(key, typeClass, method) {
|
|
90
80
|
let relationshipKey = this.keyForRelationship(key);
|
|
91
|
-
|
|
92
81
|
return `${relationshipKey}Type`;
|
|
93
82
|
},
|
|
94
|
-
|
|
95
83
|
/**
|
|
96
84
|
Normalizes a part of the JSON payload returned by
|
|
97
85
|
the server. You should override this method, munge the hash
|
|
98
86
|
and call super if you have generic normalization to do.
|
|
99
|
-
|
|
100
|
-
It takes the type of the record that is being normalized
|
|
87
|
+
It takes the type of the record that is being normalized
|
|
101
88
|
(as a Model class), the property where the hash was
|
|
102
89
|
originally found, and the hash to normalize.
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
```js
|
|
90
|
+
For example, if you have a payload that looks like this:
|
|
91
|
+
```js
|
|
107
92
|
{
|
|
108
93
|
"post": {
|
|
109
94
|
"id": 1,
|
|
@@ -119,40 +104,31 @@ const RESTSerializer = JSONSerializer.extend({
|
|
|
119
104
|
}]
|
|
120
105
|
}
|
|
121
106
|
```
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
* With `App.Post`, `"posts"` and `{ id: 1, title: "Rails is omakase", ... }`
|
|
107
|
+
The `normalize` method will be called three times:
|
|
108
|
+
* With `App.Post`, `"posts"` and `{ id: 1, title: "Rails is omakase", ... }`
|
|
126
109
|
* With `App.Comment`, `"comments"` and `{ id: 1, body: "FIRST" }`
|
|
127
110
|
* With `App.Comment`, `"comments"` and `{ id: 2, body: "Rails is unagi" }`
|
|
128
|
-
|
|
129
|
-
You can use this method, for example, to normalize underscored keys to camelized
|
|
111
|
+
You can use this method, for example, to normalize underscored keys to camelized
|
|
130
112
|
or other general-purpose normalizations. You will only need to implement
|
|
131
113
|
`normalize` and manipulate the payload as desired.
|
|
132
|
-
|
|
133
|
-
For example, if the `IDs` under `"comments"` are provided as `_id` instead of
|
|
114
|
+
For example, if the `IDs` under `"comments"` are provided as `_id` instead of
|
|
134
115
|
`id`, you can specify how to normalize just the comments:
|
|
135
|
-
|
|
136
|
-
```app/serializers/post.js
|
|
116
|
+
```app/serializers/post.js
|
|
137
117
|
import RESTSerializer from '@ember-data/serializer/rest';
|
|
138
|
-
|
|
139
|
-
export default class ApplicationSerializer extends RESTSerializer {
|
|
118
|
+
export default class ApplicationSerializer extends RESTSerializer {
|
|
140
119
|
normalize(model, hash, prop) {
|
|
141
120
|
if (prop === 'comments') {
|
|
142
121
|
hash.id = hash._id;
|
|
143
122
|
delete hash._id;
|
|
144
123
|
}
|
|
145
|
-
|
|
146
|
-
return super.normalize(...arguments);
|
|
124
|
+
return super.normalize(...arguments);
|
|
147
125
|
}
|
|
148
126
|
}
|
|
149
127
|
```
|
|
150
|
-
|
|
151
|
-
On each call to the `normalize` method, the third parameter (`prop`) is always
|
|
128
|
+
On each call to the `normalize` method, the third parameter (`prop`) is always
|
|
152
129
|
one of the keys that were in the original payload or in the result of another
|
|
153
130
|
normalization as `normalizeResponse`.
|
|
154
|
-
|
|
155
|
-
@method normalize
|
|
131
|
+
@method normalize
|
|
156
132
|
@public
|
|
157
133
|
@param {Model} modelClass
|
|
158
134
|
@param {Object} resourceHash
|
|
@@ -163,8 +139,7 @@ const RESTSerializer = JSONSerializer.extend({
|
|
|
163
139
|
/**
|
|
164
140
|
Normalizes an array of resource payloads and returns a JSON-API Document
|
|
165
141
|
with primary data and, if any, included data as `{ data, included }`.
|
|
166
|
-
|
|
167
|
-
@method _normalizeArray
|
|
142
|
+
@method _normalizeArray
|
|
168
143
|
@param {Store} store
|
|
169
144
|
@param {String} modelName
|
|
170
145
|
@param {Object} arrayHash
|
|
@@ -175,42 +150,36 @@ const RESTSerializer = JSONSerializer.extend({
|
|
|
175
150
|
_normalizeArray(store, modelName, arrayHash, prop) {
|
|
176
151
|
let documentHash = {
|
|
177
152
|
data: [],
|
|
178
|
-
included: []
|
|
153
|
+
included: []
|
|
179
154
|
};
|
|
180
|
-
|
|
181
155
|
let modelClass = store.modelFor(modelName);
|
|
182
156
|
let serializer = store.serializerFor(modelName);
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
157
|
+
makeArray(arrayHash).forEach(hash => {
|
|
158
|
+
let {
|
|
159
|
+
data,
|
|
160
|
+
included
|
|
161
|
+
} = this._normalizePolymorphicRecord(store, hash, prop, modelClass, serializer);
|
|
186
162
|
documentHash.data.push(data);
|
|
187
163
|
if (included) {
|
|
188
164
|
documentHash.included = documentHash.included.concat(included);
|
|
189
165
|
}
|
|
190
166
|
});
|
|
191
|
-
|
|
192
167
|
return documentHash;
|
|
193
168
|
},
|
|
194
|
-
|
|
195
169
|
_normalizePolymorphicRecord(store, hash, prop, primaryModelClass, primarySerializer) {
|
|
196
170
|
let serializer = primarySerializer;
|
|
197
171
|
let modelClass = primaryModelClass;
|
|
198
|
-
|
|
199
172
|
let primaryHasTypeAttribute = primaryModelClass.fields.has('type');
|
|
200
|
-
|
|
201
173
|
if (!primaryHasTypeAttribute && hash.type) {
|
|
202
174
|
// Support polymorphic records in async relationships
|
|
203
175
|
let modelName = this.modelNameFromPayloadKey(hash.type);
|
|
204
|
-
|
|
205
176
|
if (store.getSchemaDefinitionService().doesTypeExist(modelName)) {
|
|
206
177
|
serializer = store.serializerFor(modelName);
|
|
207
178
|
modelClass = store.modelFor(modelName);
|
|
208
179
|
}
|
|
209
180
|
}
|
|
210
|
-
|
|
211
181
|
return serializer.normalize(modelClass, hash, prop);
|
|
212
182
|
},
|
|
213
|
-
|
|
214
183
|
/**
|
|
215
184
|
@method _normalizeResponse
|
|
216
185
|
@param {Store} store
|
|
@@ -225,20 +194,14 @@ const RESTSerializer = JSONSerializer.extend({
|
|
|
225
194
|
_normalizeResponse(store, primaryModelClass, payload, id, requestType, isSingle) {
|
|
226
195
|
let documentHash = {
|
|
227
196
|
data: null,
|
|
228
|
-
included: []
|
|
197
|
+
included: []
|
|
229
198
|
};
|
|
230
|
-
|
|
231
199
|
let meta = this.extractMeta(store, primaryModelClass, payload);
|
|
232
200
|
if (meta) {
|
|
233
|
-
assert(
|
|
234
|
-
'The `meta` returned from `extractMeta` has to be an object, not "' + typeOf(meta) + '".',
|
|
235
|
-
typeOf(meta) === 'object'
|
|
236
|
-
);
|
|
201
|
+
assert('The `meta` returned from `extractMeta` has to be an object, not "' + typeOf(meta) + '".', typeOf(meta) === 'object');
|
|
237
202
|
documentHash.meta = meta;
|
|
238
203
|
}
|
|
239
|
-
|
|
240
204
|
let keys = Object.keys(payload);
|
|
241
|
-
|
|
242
205
|
for (var i = 0, length = keys.length; i < length; i++) {
|
|
243
206
|
var prop = keys[i];
|
|
244
207
|
var modelName = prop;
|
|
@@ -247,10 +210,8 @@ const RESTSerializer = JSONSerializer.extend({
|
|
|
247
210
|
/*
|
|
248
211
|
If you want to provide sideloaded records of the same type that the
|
|
249
212
|
primary data you can do that by prefixing the key with `_`.
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
```
|
|
213
|
+
Example
|
|
214
|
+
```
|
|
254
215
|
{
|
|
255
216
|
users: [
|
|
256
217
|
{ id: 1, title: 'Tom', manager: 3 },
|
|
@@ -261,74 +222,64 @@ const RESTSerializer = JSONSerializer.extend({
|
|
|
261
222
|
]
|
|
262
223
|
}
|
|
263
224
|
```
|
|
264
|
-
|
|
265
|
-
This forces `_users` to be added to `included` instead of `data`.
|
|
225
|
+
This forces `_users` to be added to `included` instead of `data`.
|
|
266
226
|
*/
|
|
267
227
|
if (prop.charAt(0) === '_') {
|
|
268
228
|
forcedSecondary = true;
|
|
269
229
|
modelName = prop.substr(1);
|
|
270
230
|
}
|
|
271
|
-
|
|
272
231
|
var typeName = this.modelNameFromPayloadKey(modelName);
|
|
273
232
|
if (!store.getSchemaDefinitionService().doesTypeExist(typeName)) {
|
|
274
233
|
warn(this.warnMessageNoModelForKey(modelName, typeName), false, {
|
|
275
|
-
id: 'ds.serializer.model-for-key-missing'
|
|
234
|
+
id: 'ds.serializer.model-for-key-missing'
|
|
276
235
|
});
|
|
277
236
|
continue;
|
|
278
237
|
}
|
|
279
|
-
|
|
280
238
|
var isPrimary = !forcedSecondary && this.isPrimaryType(store, typeName, primaryModelClass);
|
|
281
239
|
var value = payload[prop];
|
|
282
|
-
|
|
283
240
|
if (value === null) {
|
|
284
241
|
continue;
|
|
285
242
|
}
|
|
286
|
-
|
|
287
|
-
assert(
|
|
288
|
-
'The adapter returned an array for the primary data of a `queryRecord` response. `queryRecord` should return a single record.',
|
|
289
|
-
!(requestType === 'queryRecord' && isPrimary && Array.isArray(value))
|
|
290
|
-
);
|
|
243
|
+
assert('The adapter returned an array for the primary data of a `queryRecord` response. `queryRecord` should return a single record.', !(requestType === 'queryRecord' && isPrimary && Array.isArray(value)));
|
|
291
244
|
|
|
292
245
|
/*
|
|
293
246
|
Support primary data as an object instead of an array.
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
```
|
|
247
|
+
Example
|
|
248
|
+
```
|
|
298
249
|
{
|
|
299
250
|
user: { id: 1, title: 'Tom', manager: 3 }
|
|
300
251
|
}
|
|
301
252
|
```
|
|
302
253
|
*/
|
|
303
254
|
if (isPrimary && !Array.isArray(value)) {
|
|
304
|
-
let {
|
|
255
|
+
let {
|
|
256
|
+
data,
|
|
257
|
+
included
|
|
258
|
+
} = this._normalizePolymorphicRecord(store, value, prop, primaryModelClass, this);
|
|
305
259
|
documentHash.data = data;
|
|
306
260
|
if (included) {
|
|
307
261
|
documentHash.included = documentHash.included.concat(included);
|
|
308
262
|
}
|
|
309
263
|
continue;
|
|
310
264
|
}
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
265
|
+
let {
|
|
266
|
+
data,
|
|
267
|
+
included
|
|
268
|
+
} = this._normalizeArray(store, typeName, value, prop);
|
|
314
269
|
if (included) {
|
|
315
270
|
documentHash.included = documentHash.included.concat(included);
|
|
316
271
|
}
|
|
317
|
-
|
|
318
272
|
if (isSingle) {
|
|
319
|
-
data.forEach(
|
|
273
|
+
data.forEach(resource => {
|
|
320
274
|
/*
|
|
321
275
|
Figures out if this is the primary record or not.
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
1. The record with the same ID as the original request
|
|
276
|
+
It's either:
|
|
277
|
+
1. The record with the same ID as the original request
|
|
326
278
|
2. If it's a newly created record without an ID, the first record
|
|
327
279
|
in the array
|
|
328
280
|
*/
|
|
329
281
|
let isUpdatedRecord = isPrimary && coerceId(resource.id) === id;
|
|
330
282
|
let isFirstCreatedRecord = isPrimary && !id && !documentHash.data;
|
|
331
|
-
|
|
332
283
|
if (isFirstCreatedRecord || isUpdatedRecord) {
|
|
333
284
|
documentHash.data = resource;
|
|
334
285
|
} else {
|
|
@@ -345,19 +296,15 @@ const RESTSerializer = JSONSerializer.extend({
|
|
|
345
296
|
}
|
|
346
297
|
}
|
|
347
298
|
}
|
|
348
|
-
|
|
349
299
|
return documentHash;
|
|
350
300
|
},
|
|
351
|
-
|
|
352
301
|
isPrimaryType(store, modelName, primaryModelClass) {
|
|
353
302
|
return dasherize(modelName) === primaryModelClass.modelName;
|
|
354
303
|
},
|
|
355
|
-
|
|
356
304
|
/**
|
|
357
305
|
This method allows you to push a payload containing top-level
|
|
358
306
|
collections of records organized per type.
|
|
359
|
-
|
|
360
|
-
```js
|
|
307
|
+
```js
|
|
361
308
|
{
|
|
362
309
|
"posts": [{
|
|
363
310
|
"id": "1",
|
|
@@ -375,12 +322,10 @@ const RESTSerializer = JSONSerializer.extend({
|
|
|
375
322
|
}]
|
|
376
323
|
}
|
|
377
324
|
```
|
|
378
|
-
|
|
379
|
-
It will first normalize the payload, so you can use this to push
|
|
325
|
+
It will first normalize the payload, so you can use this to push
|
|
380
326
|
in data streaming in from your server structured the same way
|
|
381
327
|
that fetches and saves are structured.
|
|
382
|
-
|
|
383
|
-
@method pushPayload
|
|
328
|
+
@method pushPayload
|
|
384
329
|
@public
|
|
385
330
|
@param {Store} store
|
|
386
331
|
@param {Object} payload
|
|
@@ -388,67 +333,58 @@ const RESTSerializer = JSONSerializer.extend({
|
|
|
388
333
|
pushPayload(store, payload) {
|
|
389
334
|
let documentHash = {
|
|
390
335
|
data: [],
|
|
391
|
-
included: []
|
|
336
|
+
included: []
|
|
392
337
|
};
|
|
393
|
-
|
|
394
338
|
for (var prop in payload) {
|
|
395
339
|
var modelName = this.modelNameFromPayloadKey(prop);
|
|
396
340
|
if (!store.getSchemaDefinitionService().doesTypeExist(modelName)) {
|
|
397
341
|
warn(this.warnMessageNoModelForKey(prop, modelName), false, {
|
|
398
|
-
id: 'ds.serializer.model-for-key-missing'
|
|
342
|
+
id: 'ds.serializer.model-for-key-missing'
|
|
399
343
|
});
|
|
400
344
|
continue;
|
|
401
345
|
}
|
|
402
346
|
var type = store.modelFor(modelName);
|
|
403
347
|
var typeSerializer = store.serializerFor(type.modelName);
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
348
|
+
makeArray(payload[prop]).forEach(hash => {
|
|
349
|
+
let {
|
|
350
|
+
data,
|
|
351
|
+
included
|
|
352
|
+
} = typeSerializer.normalize(type, hash, prop);
|
|
407
353
|
documentHash.data.push(data);
|
|
408
354
|
if (included) {
|
|
409
355
|
documentHash.included = documentHash.included.concat(included);
|
|
410
356
|
}
|
|
411
357
|
});
|
|
412
358
|
}
|
|
413
|
-
|
|
414
359
|
store.push(documentHash);
|
|
415
360
|
},
|
|
416
|
-
|
|
417
361
|
/**
|
|
418
362
|
This method is used to convert each JSON root key in the payload
|
|
419
363
|
into a modelName that it can use to look up the appropriate model for
|
|
420
364
|
that part of the payload.
|
|
421
|
-
|
|
422
|
-
For example, your server may send a model name that does not correspond with
|
|
365
|
+
For example, your server may send a model name that does not correspond with
|
|
423
366
|
the name of the model in your app. Let's take a look at an example model,
|
|
424
367
|
and an example payload:
|
|
425
|
-
|
|
426
|
-
```app/models/post.js
|
|
368
|
+
```app/models/post.js
|
|
427
369
|
import Model from '@ember-data/model';
|
|
428
|
-
|
|
429
|
-
export default class Post extends Model {}
|
|
370
|
+
export default class Post extends Model {}
|
|
430
371
|
```
|
|
431
|
-
|
|
432
|
-
```javascript
|
|
372
|
+
```javascript
|
|
433
373
|
{
|
|
434
374
|
"blog/post": {
|
|
435
375
|
"id": "1
|
|
436
376
|
}
|
|
437
377
|
}
|
|
438
378
|
```
|
|
439
|
-
|
|
440
|
-
Ember Data is going to normalize the payload's root key for the modelName. As a result,
|
|
379
|
+
Ember Data is going to normalize the payload's root key for the modelName. As a result,
|
|
441
380
|
it will try to look up the "blog/post" model. Since we don't have a model called "blog/post"
|
|
442
381
|
(or a file called app/models/blog/post.js in ember-cli), Ember Data will throw an error
|
|
443
382
|
because it cannot find the "blog/post" model.
|
|
444
|
-
|
|
445
|
-
Since we want to remove this namespace, we can define a serializer for the application that will
|
|
383
|
+
Since we want to remove this namespace, we can define a serializer for the application that will
|
|
446
384
|
remove "blog/" from the payload key whenver it's encountered by Ember Data:
|
|
447
|
-
|
|
448
|
-
```app/serializers/application.js
|
|
385
|
+
```app/serializers/application.js
|
|
449
386
|
import RESTSerializer from '@ember-data/serializer/rest';
|
|
450
|
-
|
|
451
|
-
export default class ApplicationSerializer extends RESTSerializer {
|
|
387
|
+
export default class ApplicationSerializer extends RESTSerializer {
|
|
452
388
|
modelNameFromPayloadKey(payloadKey) {
|
|
453
389
|
if (payloadKey === 'blog/post') {
|
|
454
390
|
return super.modelNameFromPayloadKey(payloadKey.replace('blog/', ''));
|
|
@@ -458,16 +394,13 @@ const RESTSerializer = JSONSerializer.extend({
|
|
|
458
394
|
}
|
|
459
395
|
}
|
|
460
396
|
```
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
By default the modelName for a model is its
|
|
397
|
+
After refreshing, Ember Data will appropriately look up the "post" model.
|
|
398
|
+
By default the modelName for a model is its
|
|
465
399
|
name in dasherized form. This means that a payload key like "blogPost" would be
|
|
466
400
|
normalized to "blog-post" when Ember Data looks up the model. Usually, Ember Data
|
|
467
401
|
can use the correct inflection to do this for you. Most of the time, you won't
|
|
468
402
|
need to override `modelNameFromPayloadKey` for this purpose.
|
|
469
|
-
|
|
470
|
-
@method modelNameFromPayloadKey
|
|
403
|
+
@method modelNameFromPayloadKey
|
|
471
404
|
@public
|
|
472
405
|
@param {String} key
|
|
473
406
|
@return {String} the model's modelName
|
|
@@ -475,157 +408,118 @@ const RESTSerializer = JSONSerializer.extend({
|
|
|
475
408
|
modelNameFromPayloadKey(key) {
|
|
476
409
|
return singularize(dasherize(key));
|
|
477
410
|
},
|
|
478
|
-
|
|
479
411
|
// SERIALIZE
|
|
480
412
|
|
|
481
413
|
/**
|
|
482
414
|
Called when a record is saved in order to convert the
|
|
483
415
|
record into JSON.
|
|
484
|
-
|
|
485
|
-
By default, it creates a JSON object with a key for
|
|
416
|
+
By default, it creates a JSON object with a key for
|
|
486
417
|
each attribute and belongsTo relationship.
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
```app/models/comment.js
|
|
418
|
+
For example, consider this model:
|
|
419
|
+
```app/models/comment.js
|
|
491
420
|
import Model, { attr, belongsTo } from '@ember-data/model';
|
|
492
|
-
|
|
493
|
-
export default class Comment extends Model {
|
|
421
|
+
export default class Comment extends Model {
|
|
494
422
|
@attr title
|
|
495
423
|
@attr body
|
|
496
|
-
|
|
497
|
-
@belongsTo('user') author
|
|
424
|
+
@belongsTo('user') author
|
|
498
425
|
}
|
|
499
426
|
```
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
```js
|
|
427
|
+
The default serialization would create a JSON object like:
|
|
428
|
+
```js
|
|
504
429
|
{
|
|
505
430
|
"title": "Rails is unagi",
|
|
506
431
|
"body": "Rails? Omakase? O_O",
|
|
507
432
|
"author": 12
|
|
508
433
|
}
|
|
509
434
|
```
|
|
510
|
-
|
|
511
|
-
By default, attributes are passed through as-is, unless
|
|
435
|
+
By default, attributes are passed through as-is, unless
|
|
512
436
|
you specified an attribute type (`attr('date')`). If
|
|
513
437
|
you specify a transform, the JavaScript value will be
|
|
514
438
|
serialized when inserted into the JSON hash.
|
|
515
|
-
|
|
516
|
-
By default, belongs-to relationships are converted into
|
|
439
|
+
By default, belongs-to relationships are converted into
|
|
517
440
|
IDs when inserted into the JSON hash.
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
`serialize` takes an options hash with a single option:
|
|
441
|
+
## IDs
|
|
442
|
+
`serialize` takes an options hash with a single option:
|
|
522
443
|
`includeId`. If this option is `true`, `serialize` will,
|
|
523
444
|
by default include the ID in the JSON object it builds.
|
|
524
|
-
|
|
525
|
-
The adapter passes in `includeId: true` when serializing
|
|
445
|
+
The adapter passes in `includeId: true` when serializing
|
|
526
446
|
a record for `createRecord`, but not for `updateRecord`.
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
Your server may expect a different JSON format than the
|
|
447
|
+
## Customization
|
|
448
|
+
Your server may expect a different JSON format than the
|
|
531
449
|
built-in serialization format.
|
|
532
|
-
|
|
533
|
-
In that case, you can implement `serialize` yourself and
|
|
450
|
+
In that case, you can implement `serialize` yourself and
|
|
534
451
|
return a JSON hash of your choosing.
|
|
535
|
-
|
|
536
|
-
```app/serializers/post.js
|
|
452
|
+
```app/serializers/post.js
|
|
537
453
|
import RESTSerializer from '@ember-data/serializer/rest';
|
|
538
|
-
|
|
539
|
-
export default class ApplicationSerializer extends RESTSerializer {
|
|
454
|
+
export default class ApplicationSerializer extends RESTSerializer {
|
|
540
455
|
serialize(snapshot, options) {
|
|
541
456
|
let json = {
|
|
542
457
|
POST_TTL: snapshot.attr('title'),
|
|
543
458
|
POST_BDY: snapshot.attr('body'),
|
|
544
459
|
POST_CMS: snapshot.hasMany('comments', { ids: true })
|
|
545
460
|
};
|
|
546
|
-
|
|
547
|
-
if (options.includeId) {
|
|
461
|
+
if (options.includeId) {
|
|
548
462
|
json.POST_ID_ = snapshot.id;
|
|
549
463
|
}
|
|
550
|
-
|
|
551
|
-
return json;
|
|
464
|
+
return json;
|
|
552
465
|
}
|
|
553
466
|
}
|
|
554
467
|
```
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
If you want to define a serializer for your entire
|
|
468
|
+
## Customizing an App-Wide Serializer
|
|
469
|
+
If you want to define a serializer for your entire
|
|
559
470
|
application, you'll probably want to use `eachAttribute`
|
|
560
471
|
and `eachRelationship` on the record.
|
|
561
|
-
|
|
562
|
-
```app/serializers/application.js
|
|
472
|
+
```app/serializers/application.js
|
|
563
473
|
import RESTSerializer from '@ember-data/serializer/rest';
|
|
564
474
|
import { pluralize } from '<app-name>/utils/string-utils';
|
|
565
|
-
|
|
566
|
-
export default class ApplicationSerializer extends RESTSerializer {
|
|
475
|
+
export default class ApplicationSerializer extends RESTSerializer {
|
|
567
476
|
serialize(snapshot, options) {
|
|
568
477
|
let json = {};
|
|
569
|
-
|
|
570
|
-
snapshot.eachAttribute(function(name) {
|
|
478
|
+
snapshot.eachAttribute(function(name) {
|
|
571
479
|
json[serverAttributeName(name)] = snapshot.attr(name);
|
|
572
480
|
});
|
|
573
|
-
|
|
574
|
-
snapshot.eachRelationship(function(name, relationship) {
|
|
481
|
+
snapshot.eachRelationship(function(name, relationship) {
|
|
575
482
|
if (relationship.kind === 'hasMany') {
|
|
576
483
|
json[serverHasManyName(name)] = snapshot.hasMany(name, { ids: true });
|
|
577
484
|
}
|
|
578
485
|
});
|
|
579
|
-
|
|
580
|
-
if (options.includeId) {
|
|
486
|
+
if (options.includeId) {
|
|
581
487
|
json.ID_ = snapshot.id;
|
|
582
488
|
}
|
|
583
|
-
|
|
584
|
-
return json;
|
|
489
|
+
return json;
|
|
585
490
|
}
|
|
586
491
|
}
|
|
587
|
-
|
|
588
|
-
function serverAttributeName(attribute) {
|
|
492
|
+
function serverAttributeName(attribute) {
|
|
589
493
|
return attribute.underscore().toUpperCase();
|
|
590
494
|
}
|
|
591
|
-
|
|
592
|
-
function serverHasManyName(name) {
|
|
495
|
+
function serverHasManyName(name) {
|
|
593
496
|
return serverAttributeName(singularize(name)) + "_IDS";
|
|
594
497
|
}
|
|
595
498
|
```
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
```js
|
|
499
|
+
This serializer will generate JSON that looks like this:
|
|
500
|
+
```js
|
|
600
501
|
{
|
|
601
502
|
"TITLE": "Rails is omakase",
|
|
602
503
|
"BODY": "Yep. Omakase.",
|
|
603
504
|
"COMMENT_IDS": [ 1, 2, 3 ]
|
|
604
505
|
}
|
|
605
506
|
```
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
If you just want to do some small tweaks on the default JSON,
|
|
507
|
+
## Tweaking the Default JSON
|
|
508
|
+
If you just want to do some small tweaks on the default JSON,
|
|
610
509
|
you can call super first and make the tweaks on the returned
|
|
611
510
|
JSON.
|
|
612
|
-
|
|
613
|
-
```app/serializers/post.js
|
|
511
|
+
```app/serializers/post.js
|
|
614
512
|
import RESTSerializer from '@ember-data/serializer/rest';
|
|
615
|
-
|
|
616
|
-
export default class ApplicationSerializer extends RESTSerializer {
|
|
513
|
+
export default class ApplicationSerializer extends RESTSerializer {
|
|
617
514
|
serialize(snapshot, options) {
|
|
618
515
|
let json = super.serialize(snapshot, options);
|
|
619
|
-
|
|
620
|
-
json.subject = json.title;
|
|
516
|
+
json.subject = json.title;
|
|
621
517
|
delete json.title;
|
|
622
|
-
|
|
623
|
-
return json;
|
|
518
|
+
return json;
|
|
624
519
|
}
|
|
625
520
|
}
|
|
626
521
|
```
|
|
627
|
-
|
|
628
|
-
@method serialize
|
|
522
|
+
@method serialize
|
|
629
523
|
@public
|
|
630
524
|
@param {Snapshot} snapshot
|
|
631
525
|
@param {Object} options
|
|
@@ -634,28 +528,23 @@ const RESTSerializer = JSONSerializer.extend({
|
|
|
634
528
|
serialize(snapshot, options) {
|
|
635
529
|
return this._super(...arguments);
|
|
636
530
|
},
|
|
637
|
-
|
|
638
531
|
/**
|
|
639
532
|
You can use this method to customize the root keys serialized into the JSON.
|
|
640
533
|
The hash property should be modified by reference (possibly using something like _.extend)
|
|
641
534
|
By default the REST Serializer sends the modelName of a model, which is a camelized
|
|
642
535
|
version of the name.
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
```app/serializers/application.js
|
|
536
|
+
For example, your server may expect underscored root objects.
|
|
537
|
+
```app/serializers/application.js
|
|
647
538
|
import RESTSerializer from '@ember-data/serializer/rest';
|
|
648
539
|
import { decamelize } from '<app-name>/utils/string-utils';
|
|
649
|
-
|
|
650
|
-
export default class ApplicationSerializer extends RESTSerializer {
|
|
540
|
+
export default class ApplicationSerializer extends RESTSerializer {
|
|
651
541
|
serializeIntoHash(data, type, record, options) {
|
|
652
542
|
let root = decamelize(type.modelName);
|
|
653
543
|
data[root] = this.serialize(record, options);
|
|
654
544
|
}
|
|
655
545
|
}
|
|
656
546
|
```
|
|
657
|
-
|
|
658
|
-
@method serializeIntoHash
|
|
547
|
+
@method serializeIntoHash
|
|
659
548
|
@public
|
|
660
549
|
@param {Object} hash
|
|
661
550
|
@param {Model} typeClass
|
|
@@ -666,16 +555,13 @@ const RESTSerializer = JSONSerializer.extend({
|
|
|
666
555
|
let normalizedRootKey = this.payloadKeyFromModelName(typeClass.modelName);
|
|
667
556
|
hash[normalizedRootKey] = this.serialize(snapshot, options);
|
|
668
557
|
},
|
|
669
|
-
|
|
670
558
|
/**
|
|
671
559
|
You can use `payloadKeyFromModelName` to override the root key for an outgoing
|
|
672
560
|
request. By default, the RESTSerializer returns a camelized version of the
|
|
673
561
|
model's name.
|
|
674
|
-
|
|
675
|
-
For a model called TacoParty, its `modelName` would be the string `taco-party`. The RESTSerializer
|
|
562
|
+
For a model called TacoParty, its `modelName` would be the string `taco-party`. The RESTSerializer
|
|
676
563
|
will send it to the server with `tacoParty` as the root key in the JSON payload:
|
|
677
|
-
|
|
678
|
-
```js
|
|
564
|
+
```js
|
|
679
565
|
{
|
|
680
566
|
"tacoParty": {
|
|
681
567
|
"id": "1",
|
|
@@ -683,24 +569,19 @@ const RESTSerializer = JSONSerializer.extend({
|
|
|
683
569
|
}
|
|
684
570
|
}
|
|
685
571
|
```
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
```app/serializers/application.js
|
|
572
|
+
For example, your server may expect dasherized root objects:
|
|
573
|
+
```app/serializers/application.js
|
|
690
574
|
import RESTSerializer from '@ember-data/serializer/rest';
|
|
691
575
|
import { dasherize } from '<app-name>/utils/string-utils';
|
|
692
|
-
|
|
693
|
-
export default class ApplicationSerializer extends RESTSerializer {
|
|
576
|
+
export default class ApplicationSerializer extends RESTSerializer {
|
|
694
577
|
payloadKeyFromModelName(modelName) {
|
|
695
578
|
return dasherize(modelName);
|
|
696
579
|
}
|
|
697
580
|
}
|
|
698
581
|
```
|
|
699
|
-
|
|
700
|
-
Given a `TacoParty` model, calling `save` on it would produce an outgoing
|
|
582
|
+
Given a `TacoParty` model, calling `save` on it would produce an outgoing
|
|
701
583
|
request like:
|
|
702
|
-
|
|
703
|
-
```js
|
|
584
|
+
```js
|
|
704
585
|
{
|
|
705
586
|
"taco-party": {
|
|
706
587
|
"id": "1",
|
|
@@ -708,8 +589,7 @@ const RESTSerializer = JSONSerializer.extend({
|
|
|
708
589
|
}
|
|
709
590
|
}
|
|
710
591
|
```
|
|
711
|
-
|
|
712
|
-
@method payloadKeyFromModelName
|
|
592
|
+
@method payloadKeyFromModelName
|
|
713
593
|
@public
|
|
714
594
|
@param {String} modelName
|
|
715
595
|
@return {String}
|
|
@@ -717,13 +597,11 @@ const RESTSerializer = JSONSerializer.extend({
|
|
|
717
597
|
payloadKeyFromModelName(modelName) {
|
|
718
598
|
return camelize(modelName);
|
|
719
599
|
},
|
|
720
|
-
|
|
721
600
|
/**
|
|
722
601
|
You can use this method to customize how polymorphic objects are serialized.
|
|
723
602
|
By default the REST Serializer creates the key by appending `Type` to
|
|
724
603
|
the attribute and value from the model's camelcased model name.
|
|
725
|
-
|
|
726
|
-
@method serializePolymorphicType
|
|
604
|
+
@method serializePolymorphicType
|
|
727
605
|
@public
|
|
728
606
|
@param {Snapshot} snapshot
|
|
729
607
|
@param {Object} json
|
|
@@ -733,19 +611,16 @@ const RESTSerializer = JSONSerializer.extend({
|
|
|
733
611
|
let key = relationship.key;
|
|
734
612
|
let typeKey = this.keyForPolymorphicType(key, relationship.type, 'serialize');
|
|
735
613
|
let belongsTo = snapshot.belongsTo(key);
|
|
736
|
-
|
|
737
614
|
if (isNone(belongsTo)) {
|
|
738
615
|
json[typeKey] = null;
|
|
739
616
|
} else {
|
|
740
617
|
json[typeKey] = camelize(belongsTo.modelName);
|
|
741
618
|
}
|
|
742
619
|
},
|
|
743
|
-
|
|
744
620
|
/**
|
|
745
621
|
You can use this method to customize how a polymorphic relationship should
|
|
746
622
|
be extracted.
|
|
747
|
-
|
|
748
|
-
@method extractPolymorphicRelationship
|
|
623
|
+
@method extractPolymorphicRelationship
|
|
749
624
|
@public
|
|
750
625
|
@param {Object} relationshipType
|
|
751
626
|
@param {Object} relationshipHash
|
|
@@ -753,7 +628,11 @@ const RESTSerializer = JSONSerializer.extend({
|
|
|
753
628
|
@return {Object}
|
|
754
629
|
*/
|
|
755
630
|
extractPolymorphicRelationship(relationshipType, relationshipHash, relationshipOptions) {
|
|
756
|
-
let {
|
|
631
|
+
let {
|
|
632
|
+
key,
|
|
633
|
+
resourceHash,
|
|
634
|
+
relationshipMeta
|
|
635
|
+
} = relationshipOptions;
|
|
757
636
|
|
|
758
637
|
// A polymorphic belongsTo relationship can be present in the payload
|
|
759
638
|
// either in the form where the `id` and the `type` are given:
|
|
@@ -774,37 +653,21 @@ const RESTSerializer = JSONSerializer.extend({
|
|
|
774
653
|
// the base class JSONSerializer.
|
|
775
654
|
let isPolymorphic = relationshipMeta.options.polymorphic;
|
|
776
655
|
let typeProperty = this.keyForPolymorphicType(key, relationshipType, 'deserialize');
|
|
777
|
-
|
|
778
656
|
if (isPolymorphic && resourceHash[typeProperty] !== undefined && typeof relationshipHash !== 'object') {
|
|
779
657
|
let type = this.modelNameFromPayloadKey(resourceHash[typeProperty]);
|
|
780
658
|
return {
|
|
781
659
|
id: relationshipHash,
|
|
782
|
-
type: type
|
|
660
|
+
type: type
|
|
783
661
|
};
|
|
784
662
|
}
|
|
785
|
-
|
|
786
663
|
return this._super(...arguments);
|
|
787
|
-
}
|
|
664
|
+
}
|
|
788
665
|
});
|
|
789
|
-
|
|
790
|
-
if (DEBUG) {
|
|
666
|
+
if (macroCondition(isDevelopingApp())) {
|
|
791
667
|
RESTSerializer.reopen({
|
|
792
668
|
warnMessageNoModelForKey(prop, typeKey) {
|
|
793
|
-
return (
|
|
794
|
-
|
|
795
|
-
prop +
|
|
796
|
-
'" in payload, but no model was found for model name "' +
|
|
797
|
-
typeKey +
|
|
798
|
-
'" (resolved model name using ' +
|
|
799
|
-
this.constructor.toString() +
|
|
800
|
-
'.modelNameFromPayloadKey("' +
|
|
801
|
-
prop +
|
|
802
|
-
'"))'
|
|
803
|
-
);
|
|
804
|
-
},
|
|
669
|
+
return 'Encountered "' + prop + '" in payload, but no model was found for model name "' + typeKey + '" (resolved model name using ' + this.constructor.toString() + '.modelNameFromPayloadKey("' + prop + '"))';
|
|
670
|
+
}
|
|
805
671
|
});
|
|
806
672
|
}
|
|
807
|
-
|
|
808
|
-
export { EmbeddedRecordsMixin } from './-private';
|
|
809
|
-
|
|
810
|
-
export default RESTSerializer;
|
|
673
|
+
export { RESTSerializer as default };
|