diff --git a/example/colors/app.js b/example/colors/app.js index 1e8dd9a2..e46a8ffa 100644 --- a/example/colors/app.js +++ b/example/colors/app.js @@ -3,16 +3,19 @@ var app = asteroid(); app.use(asteroid.rest()); -var Color = app.model('color'); +var schema = { + name: String +}; -Color.defineSchema({ - 'name': String -}); +var Color = app.model('color', schema); -Color - .create({name: 'red'}) - .create({name: 'green'}) - .create({name: 'blue'}); +app.dataSource('db', {adapter: 'memory'}); + +Color.dataSource('db'); + +Color.create({name: 'red'}); +Color.create({name: 'green'}); +Color.create({name: 'blue'}); app.listen(3000); diff --git a/lib/application.js b/lib/application.js index a2aac778..7daf36dd 100644 --- a/lib/application.js +++ b/lib/application.js @@ -74,12 +74,63 @@ app.define = function (name, properties, options) { var dataSource = app.dataSources[name]; dataSource.attach(this); + + var hasMany = ModelCtor.hasMany; + + // override the default relations to add shared proxy methods + // cannot expose the relation methods since they are only defined + // once you get them (eg. prototype[name]) + ModelCtor.hasMany = function (anotherClass, params) { + var origArgs = arguments; + var thisClass = this, thisClassName = this.modelName; + params = params || {}; + if (typeof anotherClass === 'string') { + params.as = anotherClass; + if (params.model) { + anotherClass = params.model; + } else { + var anotherClassName = i8n.singularize(anotherClass).toLowerCase(); + for(var name in this.schema.models) { + if (name.toLowerCase() === anotherClassName) { + anotherClass = this.schema.models[name]; + } + } + } + } + + var pluralized = i8n.pluralize(anotherClass.modelName); + var methodName = params.as || + i8n.camelize(pluralized, true); + var proxyMethodName = 'get' + i8n.titleize(pluralized, true); + + // create a proxy method + var fn = this.prototype[proxyMethodName] = function () { + // this cannot be a shared method + // because it is defined when you + // get it... + this[methodName].apply(thisClass, arguments); + }; + fn.shared = true; + fn.http = {verb: 'get', path: '/' + methodName}; + + hasMany.apply(this, arguments); + }; }; + ModelCtor.shared = true; ModelCtor.sharedCtor = function (id, fn) { - this.find(id, fn); + ModelCtor.find(id, fn); }; - ModelCtor.accepts = {arg: 'id', type: 'any'}; + ModelCtor.sharedCtor.accepts = [ + // todo... models need to expose what id type they need + {arg: 'id', type: 'number', optional: true}, + {arg: 'data', type: 'object', optional: true} + ]; + ModelCtor.sharedCtor.http = [ + {path: '/'}, + {path: '/:id'} + ]; + return (app._models[ModelCtor.pluralModelName] = ModelCtor); } @@ -105,6 +156,29 @@ app.models = function () { return models; } + +/** + * Get all remote objects. + */ + +app.remoteObjects = function () { + var result = {}; + var models = this.models(); + + // add in models + Object.keys(models) + .forEach(function (name) { + var ModelCtor = models[name]; + + // only add shared models + if(ModelCtor.shared && typeof ModelCtor.sharedCtor === 'function') { + result[name] = ModelCtor; + } + }); + + return result; +} + /** * App data sources and models. */ diff --git a/lib/middleware/rest.js b/lib/middleware/rest.js index 36c58394..e606b54a 100644 --- a/lib/middleware/rest.js +++ b/lib/middleware/rest.js @@ -20,23 +20,11 @@ function rest() { var app = req.app; var remotes = app.remotes(); + // get all remote objects + var objs = app.remoteObjects(); - - // get models - var models = app.models(); - - // export the models as remote objects - remotes.exports = models; - - Object.keys(models).forEach(function (name) { - var Model = models[name]; - - Model.sharedCtor = function (id, fn) { - // TODO this should be agnostic of behavior - Model.find(id, fn); - } - Model.sharedCtor.accepts = {arg: 'id', type: 'any'}; - }); + // export remote objects + remotes.exports = objs; var handler = remotes.handler('rest');