Support relationships for collection and ressource

This commit is contained in:
Aurélien Georget 2016-01-25 16:48:15 +01:00
parent 2868ce08ee
commit 23b306c576

View File

@ -25,55 +25,110 @@ module.exports = {
const object = this.getObject(matchedRoute);
const value = this.verifyAndSetValue(ctx, object);
ctx.response.body = this.serialize(ctx, type, object, value);
ctx.response.body = this.serialize(ctx, type, value);
},
/**
* Serialize response with JSON API specification
*/
serialize: function (ctx, type, object, value) {
serialize: function (ctx, type, value) {
// TODO:
// - Handle configuration with a file to improve flexibility of JSON API support
const toSerialize = {
topLevelLinks: {self: ctx.request.origin + ctx.request.url}
topLevelLinks: {self: ctx.request.origin + ctx.request.url},
keyForAttribute: 'camelCase',
pluralizeType: false,
typeForAttribute: function (currentType) {
if (strapi.models.hasOwnProperty(type)) {
const tryFindType = _.first(_.reject(_.map(strapi.models[type].associations, function (relation) {
return (relation.alias === currentType) ? relation.model || relation.collection : undefined;
}), _.isUndefined));
return _.isUndefined(tryFindType) ? currentType : tryFindType;
}
}
};
switch (object) {
case 'collection':
if (!_.isEmpty(value) && _.isArray(value)) {
const PK = this.getPK(type);
// TODO :
// - Detect PK and stringify the value
_.forEach(value, function (value) {
value.id = value.id.toString();
});
if (_.isArray(value) && !_.isEmpty(value)) {
// Array
if (!_.isNull(PK)) {
_.forEach(value, function (record) {
record[PK] = record[PK].toString();
});
}
toSerialize.dataLinks = {
self: function (record) {
return ctx.request.origin + ctx.request.url + '/' + record.id;
}
};
} else if (!_.isEmpty(value) && _.isObject(value)) {
// TODO :
// - Detect PK and stringify the value
toSerialize.dataLinks = {
self: function (record) {
return ctx.request.origin + ctx.request.url + '/' + record.id;
}
};
// TODO :
// - Parse the model based on the type value
// - Displayed attributes but also consider query parameters
toSerialize.attributes = _.keys(value[0]);
} else if (_.isObject(value) && !_.isEmpty(value)) {
// Object
if (!_.isNull(PK)) {
value[PK] = value[PK].toString();
}
toSerialize.attributes = ['id'];
toSerialize.attributes = _.keys(value);
}
return new JSONAPISerializer(type, value, toSerialize);
case 'ressource':
toSerialize.attributes = ['id'];
this.includedRelationShips(ctx, toSerialize, type);
return new JSONAPISerializer(type, value, toSerialize);
case 'relationships':
break;
case 'related':
break;
default:
return new JSONAPISerializer(type, value, toSerialize);
return new JSONAPISerializer(type, value, toSerialize);
},
/**
* Include relationships values to the object
*/
includedRelationShips: function (ctx, toSerialize, type) {
const self = this;
if (strapi.models.hasOwnProperty(type)) {
_.forEach(strapi.models[type].associations, function (relation) {
switch (relation.nature) {
case 'oneToOne':
case 'manyToOne':
// Object
toSerialize[relation.alias] = {
ref: self.getPK(relation.model),
attributes: _.keys(strapi.models[type].attributes),
relationshipLinks: {
self: ctx.request.origin + ctx.request.url + '/relationships/' + relation.alias,
related: ctx.request.origin + ctx.request.url
},
includedLinks: {
self: function (data, record) {
return ctx.request.origin + '/' + relation.model + '/' + record.id;
}
}
};
break;
case 'oneToMany':
case 'manyToMany':
// Array
toSerialize[relation.alias] = {
ref: self.getPK(relation.collection),
typeForAttribute: relation.collection,
attributes: _.keys(strapi.models[type].attributes),
relationshipLinks: {
self: ctx.request.origin + ctx.request.url + '/relationships/' + relation.alias,
related: ctx.request.origin + ctx.request.url
},
includedLinks: {
self: function (data, record) {
return ctx.request.origin + '/' + relation.collection + '/' + record.id;
}
}
};
break;
default:
}
});
}
},
@ -148,16 +203,15 @@ module.exports = {
*/
getObject: function (matchedRoute) {
// Top level route
// TODO:
// - Improve way to detect collection/ressource/relationships/related
switch (_.size(matchedRoute.regexp.keys)) {
case 0:
// Collection
return 'collection';
case 1:
// Ressource
return 'ressource';
case 2:
// Relationships or related ressource
return (matchedRoute.path.indexOf('relationships')) ? 'relationships' : 'related';
default:
return 'collection';
@ -169,10 +223,35 @@ module.exports = {
*/
getType: function (supposedType) {
// TODO:
// - Parse the URL and try to extract useful information to find the type
if (strapi.models.hasOwnProperty(supposedType.toLowerCase())) {
return supposedType.toLowerCase();
} else {
return 'Unknow';
return null;
}
},
/**
* Find primary key
*/
getPK: function (type) {
if (!strapi.models.hasOwnProperty(type)) {
return null;
}
const PK = _.findKey(strapi.models[type].attributes, {primaryKey: true});
if (!_.isUndefined(PK)) {
return PK;
} else if (strapi.models[type].attributes.hasOwnProperty('id')) {
return 'id';
} else if (strapi.models[type].attributes.hasOwnProperty('uuid')) {
return 'uuid';
}
return null;
}
};