@balderdash/sails-edge
Version:
API-driven framework for building realtime apps, using MVC conventions (based on Express and Socket.io)
76 lines (62 loc) • 2.69 kB
JavaScript
/**
* Module dependencies
*/
var util = require('util'),
actionUtil = require('../actionUtil');
/**
* Populate (or "expand") an association
*
* get /model/:parentid/relation
* get /model/:parentid/relation/:id
*
* @param {Integer|String} parentid - the unique id of the parent instance
* @param {Integer|String} id - the unique id of the particular child instance you'd like to look up within this relation
* @param {Object} where - the find criteria (passed directly to the ORM)
* @param {Integer} limit - the maximum number of records to send back (useful for pagination)
* @param {Integer} skip - the number of records to skip (useful for pagination)
* @param {String} sort - the order of returned records, e.g. `name ASC` or `age DESC`
*
* @option {String} model - the identity of the model
* @option {String} alias - the name of the association attribute (aka "alias")
*/
module.exports = function expand(req, res) {
var Model = actionUtil.parseModel(req);
var relation = req.options.alias;
if (!relation || !Model) return res.serverError();
// Allow customizable blacklist for params.
req.options.criteria = req.options.criteria || {};
req.options.criteria.blacklist = req.options.criteria.blacklist || ['limit', 'skip', 'sort', 'id', 'parentid'];
var parentPk = req.param('parentid');
// Determine whether to populate using a criteria, or the
// specified primary key of the child record, or with no
// filter at all.
var childPk = actionUtil.parsePk(req);
// Coerce the child PK to an integer if necessary
if (childPk) {
if (Model.attributes[Model.primaryKey].type == 'integer') {
childPk = +childPk || 0;
}
}
var where = childPk ? {id: [childPk]} : actionUtil.parseCriteria(req);
var populate = sails.util.objCompact({
where: where,
skip: actionUtil.parseSkip(req),
limit: actionUtil.parseLimit(req),
sort: actionUtil.parseSort(req)
});
Model
.findOne(parentPk)
.populate(relation, populate)
.exec(function found(err, matchingRecord) {
if (err) return res.serverError(err);
if (!matchingRecord) return res.notFound('No record found with the specified id.');
if (!matchingRecord[relation]) return res.notFound(util.format('Specified record (%s) is missing relation `%s`', parentPk, relation));
// Subcribe to instance, if relevant
// TODO: only subscribe to populated attribute- not the entire model
if (sails.hooks.pubsub && req.isSocket) {
Model.subscribe(req, matchingRecord);
actionUtil.subscribeDeep(req, matchingRecord);
}
return res.ok(matchingRecord[relation]);
});
};