diff --git a/lib/models/model.js b/lib/models/model.js index 6fa5c312..1d917ca6 100644 --- a/lib/models/model.js +++ b/lib/models/model.js @@ -184,12 +184,17 @@ Model.setup = function () { // resolve relation functions sharedClass.resolve(function resolver(define) { var relations = ModelCtor.relations; - if(!relations) return; + if (!relations) { + return; + } // get the relations - for(var relationName in relations) { + for (var relationName in relations) { var relation = relations[relationName]; - if(relation.type === 'belongsTo') { + if (relation.type === 'belongsTo') { ModelCtor.belongsToRemoting(relationName, relation, define) + } else if (relation.type === 'hasMany') { + ModelCtor.hasManyRemoting(relationName, relation, define); + ModelCtor.scopeRemoting(relationName, relation, define); } else { ModelCtor.scopeRemoting(relationName, relation, define); } @@ -342,6 +347,78 @@ Model.belongsToRemoting = function(relationName, relation, define) { }, fn); } +Model.hasManyRemoting = function (relationName, relation, define) { + var findByIdFunc = this.prototype['__findById__' + relationName]; + define('__findById__' + relationName, { + isStatic: false, + http: {verb: 'get', path: '/' + relationName + '/:fk'}, + accepts: {arg: 'fk', type: 'any', + description: 'Foreign key for ' + relationName, required: true, + http: {source: 'path'}}, + description: 'Find a related item by id for ' + relationName, + returns: {arg: 'result', type: relation.modelTo.modelName, root: true} + }, findByIdFunc); + + var destroyByIdFunc = this.prototype['__destroyById__' + relationName]; + define('__destroyById__' + relationName, { + isStatic: false, + http: {verb: 'delete', path: '/' + relationName + '/:fk'}, + accepts: {arg: 'fk', type: 'any', + description: 'Foreign key for ' + relationName, required: true, + http: {source: 'path'}}, + description: 'Delete a related item by id for ' + relationName, + returns: {} + }, destroyByIdFunc); + + var updateByIdFunc = this.prototype['__updateById__' + relationName]; + define('__updateById__' + relationName, { + isStatic: false, + http: {verb: 'put', path: '/' + relationName + '/:fk'}, + accepts: {arg: 'fk', type: 'any', + description: 'Foreign key for ' + relationName, required: true, + http: {source: 'path'}}, + description: 'Update a related item by id for ' + relationName, + returns: {arg: 'result', type: relation.modelTo.modelName, root: true} + }, updateByIdFunc); + + if (relation.modelThrough) { + var addFunc = this.prototype['__link__' + relationName]; + define('__link__' + relationName, { + isStatic: false, + http: {verb: 'put', path: '/' + relationName + '/rel/:fk'}, + accepts: {arg: 'fk', type: 'any', + description: 'Foreign key for ' + relationName, required: true, + http: {source: 'path'}}, + description: 'Add a related item by id for ' + relationName, + returns: {arg: relationName, type: relation.modelThrough.modelName, root: true} + }, addFunc); + + var removeFunc = this.prototype['__unlink__' + relationName]; + define('__unlink__' + relationName, { + isStatic: false, + http: {verb: 'delete', path: '/' + relationName + '/rel/:fk'}, + accepts: {arg: 'fk', type: 'any', + description: 'Foreign key for ' + relationName, required: true, + http: {source: 'path'}}, + description: 'Remove the ' + relationName + ' relation to an item by id', + returns: {} + }, removeFunc); + + // FIXME: [rfeng] How to map a function with callback(err, true|false) to HEAD? + // true --> 200 and false --> 404? + var existsFunc = this.prototype['__exists__' + relationName]; + define('__exists__' + relationName, { + isStatic: false, + http: {verb: 'head', path: '/' + relationName + '/rel/:fk'}, + accepts: {arg: 'fk', type: 'any', + description: 'Foreign key for ' + relationName, required: true, + http: {source: 'path'}}, + description: 'Check the existence of ' + relationName + ' relation to an item by id', + returns: {} + }, existsFunc); + } +}; + Model.scopeRemoting = function(relationName, relation, define) { var toModelName = relation.modelTo.modelName;