Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save runspired/bf2872d8c03c902a380c723ff2084b9c to your computer and use it in GitHub Desktop.
Save runspired/bf2872d8c03c902a380c723ff2084b9c to your computer and use it in GitHub Desktop.
push-with-spread
import Controller from '@ember/controller';
export default class ApplicationController extends Controller {
appName = 'Ember Twiddle';
}
import Model from 'ember-data/model';
import attr from 'ember-data/attr';
import { belongsTo, hasMany } from 'ember-data/relationships';
export default class extends Model {
@hasMany('other') other;
}
import Model from 'ember-data/model';
/*
import attr from 'ember-data/attr';
import { belongsTo, hasMany } from 'ember-data/relationships';
*/
export default class extends Model {
}
import Route from '@ember/routing/route';
export default Route.extend({
model() {
// Step 1: Create a very large array to sideload into the store
let payload = new Array(200000)
.fill(null)
.map((_, id) => ({ id, type: 'other' }));
// Step 2: Load in the very large array beside a primary array of whatever length
let serializer = this.store.serializerFor('obj');
let model = this.store.modelFor('obj');
try {
let normalized = serializer.normalizeArrayResponse(this.store, model, {
obj: [{ id: 1 }],
other: payload,
})
this.store.push(normalized);
return {
obj: this.store.peekAll('obj'),
other: this.store.peekAll('other'),
};
} catch (err) {
// Step 3: Receive max stack error
return { err };
}
}
});
/**
* @module @ember-data/serializer/rest
*/
import { camelize } from '@ember/string';
import { isNone, typeOf } from '@ember/utils';
const DEBUG = true;
import Ember from "ember";
const { get, makeArray, assert, deprecate, warn } = Ember;
import { singularize } from 'ember-inflector';
import JSONSerializer from '@ember-data/serializer/json';
import { normalizeModelName } from '@ember-data/store';
import { coerceId } from '@ember-data/store/-private';
function modelHasAttributeOrRelationshipNamedType(modelClass) {
return get(modelClass, 'attributes').has('type') || get(modelClass, 'relationshipsByName').has('type');
}
const RESTSerializer = JSONSerializer.extend({
keyForPolymorphicType(key, typeClass, method) {
let relationshipKey = this.keyForRelationship(key);
return `${relationshipKey}Type`;
},
_normalizeArray(store, modelName, arrayHash, prop) {
let documentHash = {
data: [],
included: [],
};
let modelClass = store.modelFor(modelName);
let serializer = store.serializerFor(modelName);
makeArray(arrayHash).forEach((hash) => {
let { data, included } = this._normalizePolymorphicRecord(store, hash, prop, modelClass, serializer);
documentHash.data.push(data);
if (included) {
documentHash.included.push(...included);
}
});
return documentHash;
},
_normalizePolymorphicRecord(store, hash, prop, primaryModelClass, primarySerializer) {
let serializer = primarySerializer;
let modelClass = primaryModelClass;
let primaryHasTypeAttribute = modelHasAttributeOrRelationshipNamedType(primaryModelClass);
if (!primaryHasTypeAttribute && hash.type) {
// Support polymorphic records in async relationships
let modelName = this.modelNameFromPayloadKey(hash.type);
if (store._hasModelFor(modelName)) {
serializer = store.serializerFor(modelName);
modelClass = store.modelFor(modelName);
}
}
return serializer.normalize(modelClass, hash, prop);
},
_normalizeResponse(store, primaryModelClass, payload, id, requestType, isSingle) {
let documentHash = {
data: null,
included: [],
};
let meta = this.extractMeta(store, primaryModelClass, payload);
if (meta) {
assert(
'The `meta` returned from `extractMeta` has to be an object, not "' + typeOf(meta) + '".',
typeOf(meta) === 'object'
);
documentHash.meta = meta;
}
let keys = Object.keys(payload);
for (var i = 0, length = keys.length; i < length; i++) {
var prop = keys[i];
var modelName = prop;
var forcedSecondary = false;
if (prop.charAt(0) === '_') {
forcedSecondary = true;
modelName = prop.substr(1);
}
var typeName = this.modelNameFromPayloadKey(modelName);
if (!store._hasModelFor(typeName)) {
warn(this.warnMessageNoModelForKey(modelName, typeName), false, {
id: 'ds.serializer.model-for-key-missing',
});
continue;
}
var isPrimary = !forcedSecondary && this.isPrimaryType(store, typeName, primaryModelClass);
var value = payload[prop];
if (value === null) {
continue;
}
if (DEBUG) {
let isQueryRecordAnArray = requestType === 'queryRecord' && isPrimary && Array.isArray(value);
let message =
'The adapter returned an array for the primary data of a `queryRecord` response. This is deprecated as `queryRecord` should return a single record.';
deprecate(message, !isQueryRecordAnArray, {
id: 'ds.serializer.rest.queryRecord-array-response',
until: '3.0',
url: 'https://deprecations.emberjs.com/ember-data/v2.x/#toc_store-queryrecord-array-response-with-restserializer',
for: '@ember-data/serializer',
since: {
available: '3.0',
enabled: '3.0',
},
});
}
if (isPrimary && !Array.isArray(value)) {
let { data, included } = this._normalizePolymorphicRecord(store, value, prop, primaryModelClass, this);
documentHash.data = data;
if (included) {
documentHash.included.push(...included);
}
continue;
}
let { data, included } = this._normalizeArray(store, typeName, value, prop);
if (included) {
documentHash.included.push(...included);
}
if (isSingle) {
data.forEach((resource) => {
let isUpdatedRecord = isPrimary && coerceId(resource.id) === id;
let isFirstCreatedRecord = isPrimary && !id && !documentHash.data;
if (isFirstCreatedRecord || isUpdatedRecord) {
documentHash.data = resource;
} else {
documentHash.included.push(resource);
}
});
} else {
if (isPrimary) {
documentHash.data = data;
} else {
if (data) {
documentHash.included.push(...data);
}
}
}
}
return documentHash;
},
isPrimaryType(store, modelName, primaryModelClass) {
return normalizeModelName(modelName) === primaryModelClass.modelName;
},
pushPayload(store, payload) {
let documentHash = {
data: [],
included: [],
};
for (var prop in payload) {
var modelName = this.modelNameFromPayloadKey(prop);
if (!store._hasModelFor(modelName)) {
warn(this.warnMessageNoModelForKey(prop, modelName), false, {
id: 'ds.serializer.model-for-key-missing',
});
continue;
}
var type = store.modelFor(modelName);
var typeSerializer = store.serializerFor(type.modelName);
makeArray(payload[prop]).forEach((hash) => {
let { data, included } = typeSerializer.normalize(type, hash, prop);
documentHash.data.push(data);
if (included) {
documentHash.included.push(...included);
}
});
}
store.push(documentHash);
},
modelNameFromPayloadKey(key) {
return singularize(normalizeModelName(key));
},
serialize(snapshot, options) {
return this._super(...arguments);
},
serializeIntoHash(hash, typeClass, snapshot, options) {
let normalizedRootKey = this.payloadKeyFromModelName(typeClass.modelName);
hash[normalizedRootKey] = this.serialize(snapshot, options);
},
payloadKeyFromModelName(modelName) {
return camelize(modelName);
},
serializePolymorphicType(snapshot, json, relationship) {
let key = relationship.key;
let typeKey = this.keyForPolymorphicType(key, relationship.type, 'serialize');
let belongsTo = snapshot.belongsTo(key);
if (isNone(belongsTo)) {
json[typeKey] = null;
} else {
json[typeKey] = camelize(belongsTo.modelName);
}
},
extractPolymorphicRelationship(relationshipType, relationshipHash, relationshipOptions) {
let { key, resourceHash, relationshipMeta } = relationshipOptions;
let isPolymorphic = relationshipMeta.options.polymorphic;
let typeProperty = this.keyForPolymorphicType(key, relationshipType, 'deserialize');
if (isPolymorphic && resourceHash[typeProperty] !== undefined && typeof relationshipHash !== 'object') {
let type = this.modelNameFromPayloadKey(resourceHash[typeProperty]);
return {
id: relationshipHash,
type: type,
};
}
return this._super(...arguments);
},
});
if (DEBUG) {
RESTSerializer.reopen({
warnMessageNoModelForKey(prop, typeKey) {
return (
'Encountered "' +
prop +
'" in payload, but no model was found for model name "' +
typeKey +
'" (resolved model name using ' +
this.constructor.toString() +
'.modelNameFromPayloadKey("' +
prop +
'"))'
);
},
});
}
export default RESTSerializer;
import ApplicationSerializer from './application';
import { EmbeddedRecordsMixin } from '@ember-data/serializer/rest';
const Base = ApplicationSerializer;//.extend(EmbeddedRecordsMixin);
export default class ObjSerialzier extends Base {
// attrs = {
// other: {
// embedded: 'always',
// }
// }
}
{{#if this.model.err}}
<strong style="color:red;">{{this.model.err.message}}</strong>
<p>{{this.model.err.stack}}</p>
{{else}}
<h1>There are {{this.model.obj.length}} primary <code>obj</code> records</h1>
<em>But {{this.model.other.length}} records were sideloaded</em>
{{/if}}
{
"version": "0.17.1",
"EmberENV": {
"FEATURES": {},
"_TEMPLATE_ONLY_GLIMMER_COMPONENTS": false,
"_APPLICATION_TEMPLATE_WRAPPER": true,
"_JQUERY_INTEGRATION": true
},
"options": {
"use_pods": false,
"enable-testing": false
},
"dependencies": {
"jquery": "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.js",
"ember": "3.18.1",
"ember-template-compiler": "3.18.1",
"ember-testing": "3.18.1"
},
"addons": {
"@glimmer/component": "1.0.0",
"ember-data": "3.18.0"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment