Skip to content

Instantly share code, notes, and snippets.

@samselikoff
Created December 21, 2017 13:52
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 samselikoff/b9c35c457ef4260825c862c0cbdb26e5 to your computer and use it in GitHub Desktop.
Save samselikoff/b9c35c457ef4260825c862c0cbdb26e5 to your computer and use it in GitHub Desktop.
import DS from 'ember-data';
import Ember from 'ember';
let knownReferences = function(documents) {
return documents.reduce((map, document) => {
map[`${document.type}:${document.id}`] = true;
return map;
}, {});
};
let linkedReferences = function(documents) {
return documents
.filter(document => document.relationships)
.reduce((all, document) => {
let keys = Object.keys(document.relationships);
let references = keys.reduce((found, key) => {
let relationship = document.relationships[key];
return relationship.data ? found.concat(relationship.data) : found;
}, []);
return all.concat(references);
}, []);
}
let notIn = function(map) {
return function(data) {
return !map[`${data.type}:${data.id}`];
};
};
let getLinkageData = function(document, type) {
let relationships = document.relationships || {};
let relationship = relationships[type] || {};
return relationship.data;
}
let linkedTo = function({ type, id }) {
let isLink = function(data) {
return data.type === type && data.id === id;
};
return function(document) {
let related = getLinkageData(document, type);
return Ember.isArray(related) ? related.any(isLink) : isLink(related);
}
}
let cleanDocument = function(document, { type, id }) {
let isLink = function(data) {
return data.type === type && data.id === id;
};
let related = getLinkageData(document, type);
if (Ember.isArray(related)) {
let index = related.findIndex(isLink);
related.splice(index, 1);
} else if (isLink(related)) {
document.relationships[type] = { data: null };
}
}
export default DS.JSONAPISerializer.extend({
normalizeResponse(store, primaryModelClass, payload, id, requestType) {
let included = payload.included || [];
let documents = included.concat(payload.data);
linkedReferences(documents)
.filter(notIn(knownReferences(documents)))
.forEach(missing => {
let badDocument = documents.find(linkedTo(missing));
console.warn(`
Your payload linked ${badDocument.type}:${badDocument.id} to
${missing.type}:${missing.id}, but ${missing.type}:${missing.id}
was not in the list of included documents. The link will be
removed from this payload.
`);
cleanDocument(badDocument, missing);
});
return this._super(...arguments);
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment