Skip to content

Commit

Permalink
Make EmbeddedRecordsMixin work with the new Serializer API
Browse files Browse the repository at this point in the history
  • Loading branch information
wecc committed Jun 5, 2015
1 parent 86a286d commit 5fac1e8
Show file tree
Hide file tree
Showing 2 changed files with 1,397 additions and 73 deletions.
270 changes: 197 additions & 73 deletions packages/ember-data/lib/serializers/embedded-records-mixin.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
var get = Ember.get;
var set = Ember.set;
var forEach = Ember.EnumerableUtils.forEach;
var camelize = Ember.String.camelize;

Expand Down Expand Up @@ -91,6 +93,21 @@ var camelize = Ember.String.camelize;
*/
var EmbeddedRecordsMixin = Ember.Mixin.create({

/**
This is only to be used temporarily during the transition from the old
serializer API to the new one.
@property _replaceNewSerializerAPIMethodsEmbeddedRecordsMixin
@private
*/
_replaceNewSerializerAPIMethodsEmbeddedRecordsMixin: Ember.on('init', function() {
if (Ember.FEATURES.isEnabled('ds-new-serializer-api') && this.get('isNewSerializerAPI')) {
this._extractEmbeddedRecords = this._newExtractEmbeddedRecords;
this._extractEmbeddedBelongsTo = this._newExtractEmbeddedBelongsTo;
this._extractEmbeddedHasMany = this._newExtractEmbeddedHasMany;
}
}),

/**
Normalize the record and recursively normalize/extract all the embedded records
while pushing them into the store as they are encountered
Expand Down Expand Up @@ -120,7 +137,19 @@ var EmbeddedRecordsMixin = Ember.Mixin.create({
**/
normalize: function(typeClass, hash, prop) {
var normalizedHash = this._super(typeClass, hash, prop);
return extractEmbeddedRecords(this, this.store, typeClass, normalizedHash);
return this._extractEmbeddedRecords(this, this.store, typeClass, normalizedHash);
},

/**
@method newNormalize
@param {DS.Model} modelClass
@param {Object} hash
@return {Object}
@private
*/
newNormalize: function(typeClass, hash, prop) {
var normalizedHash = this._super(typeClass, hash, prop);
return this._extractEmbeddedRecords(this, this.store, typeClass, normalizedHash);
},

keyForRelationship: function(key, typeClass, method) {
Expand Down Expand Up @@ -385,107 +414,202 @@ var EmbeddedRecordsMixin = Ember.Mixin.create({
attrsOption: function(attr) {
var attrs = this.get('attrs');
return attrs && (attrs[camelize(attr)] || attrs[attr]);
}
});
},

// chooses a relationship kind to branch which function is used to update payload
// does not change payload if attr is not embedded
function extractEmbeddedRecords(serializer, store, typeClass, partial) {

typeClass.eachRelationship(function(key, relationship) {
if (serializer.hasDeserializeRecordsOption(key)) {
var embeddedTypeClass = store.modelFor(relationship.type);
if (relationship.kind === "hasMany") {
if (relationship.options.polymorphic) {
extractEmbeddedHasManyPolymorphic(store, key, partial);
} else {
extractEmbeddedHasMany(store, key, embeddedTypeClass, partial);
/**
@method _extractEmbeddedRecords
@private
*/
_extractEmbeddedRecords: function(serializer, store, typeClass, partial) {

typeClass.eachRelationship(function(key, relationship) {
if (serializer.hasDeserializeRecordsOption(key)) {
var embeddedTypeClass = store.modelFor(relationship.type);
if (relationship.kind === "hasMany") {
if (relationship.options.polymorphic) {
this._extractEmbeddedHasManyPolymorphic(store, key, partial);
} else {
this._extractEmbeddedHasMany(store, key, embeddedTypeClass, partial);

This comment has been minimized.

Copy link
@igorT

igorT Jun 5, 2015

Member

Why are we doing this here, instead of just looping normalizeRelationship

}
}
}
if (relationship.kind === "belongsTo") {
if (relationship.options.polymorphic) {
extractEmbeddedBelongsToPolymorphic(store, key, partial);
} else {
extractEmbeddedBelongsTo(store, key, embeddedTypeClass, partial);
if (relationship.kind === "belongsTo") {
if (relationship.options.polymorphic) {
this._extractEmbeddedBelongsToPolymorphic(store, key, partial);
} else {
this._extractEmbeddedBelongsTo(store, key, embeddedTypeClass, partial);
}
}
}
}, this);

return partial;
},

/**
@method _extractEmbeddedHasMany
@private
*/
_extractEmbeddedHasMany: function(store, key, embeddedTypeClass, hash) {
if (!hash[key]) {
return hash;
}
});

return partial;
}
var ids = [];

// handles embedding for `hasMany` relationship
function extractEmbeddedHasMany(store, key, embeddedTypeClass, hash) {
if (!hash[key]) {
var embeddedSerializer = store.serializerFor(embeddedTypeClass.modelName);
forEach(hash[key], function(data) {
var embeddedRecord = embeddedSerializer.normalize(embeddedTypeClass, data, null);
store.push(embeddedTypeClass.modelName, embeddedRecord);
ids.push(embeddedRecord.id);
});

hash[key] = ids;
return hash;
}
},

var ids = [];
/**
@method _extractEmbeddedHasManyPolymorphic
@private
*/
_extractEmbeddedHasManyPolymorphic: function(store, key, hash) {
if (!hash[key]) {
return hash;
}

var embeddedSerializer = store.serializerFor(embeddedTypeClass.modelName);
forEach(hash[key], function(data) {
var embeddedRecord = embeddedSerializer.normalize(embeddedTypeClass, data, null);
store.push(embeddedTypeClass.modelName, embeddedRecord);
ids.push(embeddedRecord.id);
});
var ids = [];

hash[key] = ids;
return hash;
}
forEach(hash[key], function(data) {
var modelName = data.type;
var embeddedSerializer = store.serializerFor(modelName);
var embeddedTypeClass = store.modelFor(modelName);
// var primaryKey = embeddedSerializer.get('primaryKey');

function extractEmbeddedHasManyPolymorphic(store, key, hash) {
if (!hash[key]) {
var embeddedRecord = embeddedSerializer.normalize(embeddedTypeClass, data, null);
store.push(embeddedTypeClass.modelName, embeddedRecord);
ids.push({ id: embeddedRecord.id, type: modelName });
});

hash[key] = ids;
return hash;
}
},

var ids = [];
/**
@method _extractEmbeddedBelongsTo
@private
*/
_extractEmbeddedBelongsTo: function(store, key, embeddedTypeClass, hash) {
if (!hash[key]) {
return hash;
}

forEach(hash[key], function(data) {
var embeddedSerializer = store.serializerFor(embeddedTypeClass.modelName);
var embeddedRecord = embeddedSerializer.normalize(embeddedTypeClass, hash[key], null);
store.push(embeddedTypeClass.modelName, embeddedRecord);

hash[key] = embeddedRecord.id;
//TODO Need to add a reference to the parent later so relationship works between both `belongsTo` records
return hash;
},

/**
@method _extractEmbeddedBelongsToPolymorphic
@private
*/
_extractEmbeddedBelongsToPolymorphic: function(store, key, hash) {
if (!hash[key]) {
return hash;
}

var data = hash[key];
var modelName = data.type;
var embeddedSerializer = store.serializerFor(modelName);
var embeddedTypeClass = store.modelFor(modelName);
// var primaryKey = embeddedSerializer.get('primaryKey');

var embeddedRecord = embeddedSerializer.normalize(embeddedTypeClass, data, null);
store.push(embeddedTypeClass.modelName, embeddedRecord);
ids.push({ id: embeddedRecord.id, type: modelName });
});

hash[key] = ids;
return hash;
}

function extractEmbeddedBelongsTo(store, key, embeddedTypeClass, hash) {
if (!hash[key]) {
hash[key] = embeddedRecord.id;
hash[key + 'Type'] = modelName;
return hash;
}
},

var embeddedSerializer = store.serializerFor(embeddedTypeClass.modelName);
var embeddedRecord = embeddedSerializer.normalize(embeddedTypeClass, hash[key], null);
store.push(embeddedTypeClass.modelName, embeddedRecord);
/**
@method _newExtractEmbeddedRecords
@private
*/
_newExtractEmbeddedRecords: function(serializer, store, typeClass, partial) {
typeClass.eachRelationship((key, relationship) => {
if (serializer.hasDeserializeRecordsOption(key)) {
let embeddedTypeClass = store.modelFor(relationship.type);
if (relationship.kind === "hasMany") {
this._extractEmbeddedHasMany(store, key, embeddedTypeClass, partial, relationship);
}
if (relationship.kind === "belongsTo") {
this._extractEmbeddedBelongsTo(store, key, embeddedTypeClass, partial, relationship);
}
}
}, this);
return partial;
},

hash[key] = embeddedRecord.id;
//TODO Need to add a reference to the parent later so relationship works between both `belongsTo` records
return hash;
}
/**
@method _newExtractEmbeddedHasMany
@private
*/
_newExtractEmbeddedHasMany: function(store, key, typeClass, hash, relationshipMeta) {
let relationshipHash = get(hash, `data.relationships.${key}.data`);
if (!relationshipHash) {
return;
}

function extractEmbeddedBelongsToPolymorphic(store, key, hash) {
if (!hash[key]) {
return hash;
}
let hasMany = relationshipHash.map(item => {
let embeddedTypeClass = typeClass;
if (relationshipMeta.options.polymorphic) {
let modelName = item.type;
embeddedTypeClass = store.modelFor(modelName);
}

var data = hash[key];
var modelName = data.type;
var embeddedSerializer = store.serializerFor(modelName);
var embeddedTypeClass = store.modelFor(modelName);
let embeddedSerializer = store.serializerFor(embeddedTypeClass.modelName);
let { data, included } = embeddedSerializer.normalize(embeddedTypeClass, item, null);
hash.included = hash.included || [];
hash.included.push(data);
hash.included.push(...included);

var embeddedRecord = embeddedSerializer.normalize(embeddedTypeClass, data, null);
store.push(embeddedTypeClass.modelName, embeddedRecord);
return { id: data.id, type: embeddedTypeClass.modelName };
});

let relationship = { data: hasMany };
set(hash, `data.relationships.${key}`, relationship);
},

hash[key] = embeddedRecord.id;
hash[key + 'Type'] = modelName;
return hash;
}
/**
@method _newExtractEmbeddedBelongsTo
@private
*/
_newExtractEmbeddedBelongsTo: function(store, key, typeClass, hash, relationshipMeta) {
let relationshipHash = get(hash, `data.relationships.${key}.data`);
if (!relationshipHash) {
return;
}

let embeddedTypeClass = typeClass;
if (relationshipMeta.options.polymorphic) {
let modelName = relationshipHash.type;
embeddedTypeClass = store.modelFor(modelName);
}

let embeddedSerializer = store.serializerFor(embeddedTypeClass.modelName);
let { data, included } = embeddedSerializer.normalize(embeddedTypeClass, relationshipHash, null);
hash.included = hash.included || [];
hash.included.push(data);
hash.included.push(...included);

let belongsTo = { id: data.id, type: embeddedTypeClass.modelName };

let relationship = { data: belongsTo };
set(hash, `data.relationships.${key}`, relationship);
}
});

export default EmbeddedRecordsMixin;
Loading

0 comments on commit 5fac1e8

Please sign in to comment.