Skip to content
This repository has been archived by the owner on Jan 30, 2023. It is now read-only.

Commit

Permalink
Added blueprint controller back into core (apps may still customize b…
Browse files Browse the repository at this point in the history
…lueprints by creating api/blueprints/[find|create|update|destroy].js overrides)
  • Loading branch information
mikermcneil committed Jan 17, 2014
1 parent 85b8b82 commit d03b2eb
Show file tree
Hide file tree
Showing 6 changed files with 377 additions and 9 deletions.
5 changes: 4 additions & 1 deletion .jshintrc
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@
// Suppress warnings about "weird constructions"
// i.e. allow code like:
// (new (function OneTimeUsePrototype () { } ))
"supernew": true
"supernew": true,

// Allow backwards, node-dependency-style commas
"laxcomma": true

// "bitwise": true,
// "camelcase": true,
Expand Down
61 changes: 61 additions & 0 deletions lib/hooks/blueprints/actions/create.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/**
* Create
* (blueprint action)
*
*/
module.exports = function genericCreate (req, res) {

// Get access to `sails` (globals might be disabled) and look up the model.
var sails = req._sails;
var Model = sails.models[req.options.model];

// If no model exists for this controller, it's a 404.
if ( !Model ) return res.notFound();



// The name of the parameter to use for JSONP callbacks
var JSONP_CALLBACK_PARAM = 'callback';

// if req.transport is falsy or doesn't contain the phrase "socket"
// and JSONP is enabled for this action, we'll say we're "isJSONPCompatible"
var isJSONPCompatible = req.options.jsonp && ! ( req.transport && req.transport.match(/socket/i) );


// Create data object (monolithic combination of all parameters)
// Omit the JSONP callback parameter (if this is isJSONPCompatible)
// and params whose values are `undefined`
var data = req.params.all();
if (isJSONPCompatible) { data = sails.util.omit(data, JSONP_CALLBACK_PARAM); }




// Create new instance of model using data from params
Model.create(data).exec(function created (err, newInstance) {

// TODO: differentiate between waterline-originated validation errors
// and serious underlying issues
// TODO: Respond with badRequest if an error is encountered, w/ validation info
if (err) return res.serverError(err);

// // If 'silent' is set, don't use the built-in pubsub
// if (!req.options.silent) {
// // TODO: enable pubsub in blueprints again when new syntax if fully fleshed out
// sails.publish(newInstance, { method: 'create', data: newInstance.toJSON });
// }

// Set status code (HTTP 201: Created)
res.status(201);

// Send JSONP-friendly response if it's supported
if ( req.options.jsonp ) {
return res.jsonp(newInstance.toJSON());
}

// Otherwise, strictly JSON.
else {
return res.json(newInstance.toJSON());
}
});
};
59 changes: 59 additions & 0 deletions lib/hooks/blueprints/actions/destroy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/**
*
*/
module.exports = function destroy (req, res) {
// Locate and validate id parameter
var id = req.param('id');
if (!id) {
return res.badRequest('No id provided.');
}

// Get access to `sails` (globals might be disabled) and look up the model.
var sails = req._sails;
var Model = sails.models[req.options.model];

// If no model exists for this controller, it's a 404.
if ( !Model ) return res.notFound();

// The name of the parameter to use for JSONP callbacks
var JSONP_CALLBACK_PARAM = 'callback';

// if req.transport is falsy or doesn't contain the phrase "socket"
// and JSONP is enabled for this action, we'll say we're "isJSONPCompatible"
var isJSONPCompatible = req.options.jsonp && ! ( req.transport && req.transport.match(/socket/i) );




// Otherwise, find and destroy the model in question
Model.findOne(id).exec(function found(err, result) {

// TODO: differentiate between waterline-originated validation errors
// and serious underlying issues
// TODO: Respond with badRequest if an error is encountered, w/ validation info
if (err) return res.serverError(err);

if (!result) return res.notFound();

Model.destroy(id).exec(function destroyed(err) {
// TODO: differentiate between waterline-originated validation errors
// and serious underlying issues
// TODO: Respond with badRequest if an error is encountered, w/ validation info
if (err) return res.serverError(err);

// If 'silent' is set, don't use the built-in pubsub
// if (!req.options.silent) {
// TODO: enable pubsub in blueprints again when new syntax if fully fleshed out
// sails.publish(newInstance, { method: 'destroy', data: newInstance.toJSON });
// }

// Respond with JSON or JSONP
if ( isJSONPCompatible ) {
return res.jsonp(result);
}
else {
return res.json(result);
}
});
});
};
157 changes: 157 additions & 0 deletions lib/hooks/blueprints/actions/find.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
/**
* Find Records
*
* An API call to find and return model instances from the data adapter
* using the specified criteria. If an id was specified, just the instance
* with that unique id will be returned.
*
* @param {Integer|String} id - the unique id of the particular instance you'd like to look up
* @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`
*/

module.exports = function find (req, res) {

// Get access to `sails` (globals might be disabled) and look up the model.
var sails = req._sails;
var Model = sails.models[req.options.model];

// If no model exists for this controller, it's a 404.
if ( !Model ) return res.notFound();

// The name of the parameter to use for JSONP callbacks
var JSONP_CALLBACK_PARAM = 'callback';

// if req.transport is falsy or doesn't contain the phrase "socket"
// and JSONP is enabled for this action, we'll say we're "isJSONPCompatible"
var isJSONPCompatible = req.options.jsonp && ! ( req.transport && req.transport.match(/socket/i) );






/**
* If a valid id was specified, find the particular instance with that id.
*/
if (req.param('id')) {
Model.findOne(req.param('id')).exec(function found(err, matchingRecord) {

// TODO: differentiate between waterline-originated validation errors
// and serious underlying issues
// TODO: Respond with badRequest if an error is encountered, w/ validation info
if (err) return res.serverError(err);

// No model instance found with the specified id
if(!matchingRecord) return res.notFound();

// // TODO: enable pubsub in blueprints again when new syntax if fully fleshed out
// req.socket.subscribe(newInstance);

// toJSON() the instance.
matchingRecord = matchingRecord.toJSON();

// Otherwise serve a JSON(P) API
if ( isJSONPCompatible ) {
return res.jsonp(matchingRecord);
}
else {
return res.json(matchingRecord);
}
});
}


/**
* If no id was specified, find instances matching the specified criteria.
*/
else {

// Lookup for records that match the specified criteria
Model.find({
limit: req.param('limit') || undefined,
skip: req.param('skip') || req.param('offset') || undefined,
sort: req.param('sort') || req.param('order') || undefined,
where: parseWhereParam(req.params.all()) || undefined
}).exec(function found(err, matchingRecords) {

// TODO: differentiate between waterline-originated validation errors
// and serious underlying issues
// TODO: Respond with badRequest if an error is encountered, w/ validation info
if (err) return res.serverError(err);

// No instances found
if(!matchingRecords) return res.notFound();

// // TODO: enable pubsub in blueprints again when new syntax if fully fleshed out
// req.socket.subscribe(matchingRecords);

// toJSON() all of the model instances
matchingRecords = sails.util.invoke(matchingRecords, 'toJSON');

// Otherwise serve a JSON(P) API
if ( isJSONPCompatible ) {
return res.jsonp(matchingRecords);
}
else {
return res.json(matchingRecords);
}
});
}







// TODO:
//
// Replace the following helper with the version in sails.util:

// Attempt to parse JSON
// If the parse fails, return the error object
// If JSON is falsey, return null
// (this is so that it will be ignored if not specified)
function tryToParseJSON (json) {
if (!sails.util.isString(json)) return null;
try {
return JSON.parse(json);
}
catch (e) {
return e;
}
}

/**
* parseWhereParam
*
* @param {Object} allParams [result of calling req.params.all()]
* @return {Object} the WHERE criteria object
*/
function parseWhereParam( allParams ) {

var where = req.param('where');

// If `where` parameter is a string, try to interpret it as JSON
if (sails.util.isString(where)) {
where = tryToParseJSON(where);
}

// If `where` has not been specified, but other unbound parameter variables
// **ARE** specified, build the `where` option using them.
if (!where) {
// Prune params which aren't fit to be used as `where` criteria
// to build a proper where query
where = sails.util.omit(allParams, ['limit', 'skip', 'sort']);
where = sails.util.omit(allParams, function (p){ if (sails.util.isUndefined(p)) return true; });
if (isJSONPCompatible) { where = sails.util.omit(where, JSONP_CALLBACK_PARAM); }
}

return where;
}

};

69 changes: 69 additions & 0 deletions lib/hooks/blueprints/actions/update.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/**
* Update Record
*
* An API call to update a model instance with the specified `id`,
* treating the other unbound parameters as attributes.
*
* @param {Integer|String} id - the unique id of the particular record you'd like to update
* @param * - values to set on the record
*
*/
module.exports = function update (req, res) {

// Locate and validate id parameter
var id = req.param('id');
if (!id) {
return res.badRequest('No id provided.');
}

// Get access to `sails` (globals might be disabled) and look up the model.
var sails = req._sails;
var Model = sails.models[req.options.model];

// If no model exists for this controller, it's a 404.
if ( !Model ) return res.notFound();

// The name of the parameter to use for JSONP callbacks
var JSONP_CALLBACK_PARAM = 'callback';

// if req.transport is falsy or doesn't contain the phrase "socket"
// and JSONP is enabled for this action, we'll say we're "isJSONPCompatible"
var isJSONPCompatible = req.options.jsonp && ! ( req.transport && req.transport.match(/socket/i) );

// Create data object (monolithic combination of all parameters)
// Omit the JSONP callback parameter (if this is isJSONPCompatible)
var data = req.params.all();
if (isJSONPCompatible) { data = sails.util.omit(data, JSONP_CALLBACK_PARAM); }
// TODO: and params whose values are `undefined`





// Otherwise find and update the models in question
Model.update(id, data).exec(function updated(err, models) {
// TODO: differentiate between waterline-originated validation errors
// and serious underlying issues
// TODO: Respond with badRequest if an error is encountered, w/ validation info
if (err) return res.serverError(err);
if(!models) return res.serverError('No instances returned from update.');
if (models.length === 0) return res.notFound();

// Because this should only update a single record and update
// returns an array, just use the first item
var model = models[0];

// If 'silent' is set, don't use the built-in pubsub
// if (!req.options.silent) {
// TODO: enable pubsub in blueprints again when new syntax if fully fleshed out
// sails.publish(newInstance, { method: 'update', data: newInstance.toJSON });
// }

if ( isJSONPCompatible ) {
return res.jsonp(model.toJSON());
}
else {
return res.json(model.toJSON());
}
});
};
Loading

0 comments on commit d03b2eb

Please sign in to comment.