Refactor create model
This commit is contained in:
parent
166451443a
commit
6428000fc0
19
README.md
19
README.md
|
@ -369,6 +369,21 @@ Other wildcard examples
|
||||||
// run before any instance method eg. User.prototype.save
|
// run before any instance method eg. User.prototype.save
|
||||||
User.beforeRemote('prototype.*', ...);
|
User.beforeRemote('prototype.*', ...);
|
||||||
|
|
||||||
|
// prevent password hashes from being sent to clients
|
||||||
|
User.afterRemote('**', function (ctx, user, next) {
|
||||||
|
if(ctx.result) {
|
||||||
|
if(Array.isArray(ctx.result)) {
|
||||||
|
ctx.result.forEach(function (result) {
|
||||||
|
result.password = undefined;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
ctx.result.password = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
|
||||||
#### Context
|
#### Context
|
||||||
|
|
||||||
Remote hooks are provided with a Context `ctx` object which contains transport specific data (eg. for http: `req` and `res`). The `ctx` object also has a set of consistent apis across transports.
|
Remote hooks are provided with a Context `ctx` object which contains transport specific data (eg. for http: `req` and `res`). The `ctx` object also has a set of consistent apis across transports.
|
||||||
|
@ -377,6 +392,10 @@ Remote hooks are provided with a Context `ctx` object which contains transport s
|
||||||
|
|
||||||
A `Model` representing the user calling the method remotely. **Note:** this is undefined if the remote method is not invoked by a logged in user.
|
A `Model` representing the user calling the method remotely. **Note:** this is undefined if the remote method is not invoked by a logged in user.
|
||||||
|
|
||||||
|
##### ctx.result
|
||||||
|
|
||||||
|
During `afterRemote` hooks, `ctx.result` will contain the data about to be sent to a client. Modify this object to transform data before it is sent.
|
||||||
|
|
||||||
##### Rest
|
##### Rest
|
||||||
|
|
||||||
When [asteroid.rest](#asteroidrest) is used the following `ctx` properties are available.
|
When [asteroid.rest](#asteroidrest) is used the following `ctx` properties are available.
|
||||||
|
|
|
@ -5,8 +5,7 @@
|
||||||
var DataSource = require('jugglingdb').DataSource
|
var DataSource = require('jugglingdb').DataSource
|
||||||
, ModelBuilder = require('jugglingdb').ModelBuilder
|
, ModelBuilder = require('jugglingdb').ModelBuilder
|
||||||
, assert = require('assert')
|
, assert = require('assert')
|
||||||
, RemoteObjects = require('sl-remoting')
|
, RemoteObjects = require('sl-remoting');
|
||||||
, i8n = require('inflection');
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Export the app prototype.
|
* Export the app prototype.
|
||||||
|
@ -55,6 +54,9 @@ app._models = [];
|
||||||
app.model = function (Model) {
|
app.model = function (Model) {
|
||||||
this._models.push(Model);
|
this._models.push(Model);
|
||||||
Model.app = this;
|
Model.app = this;
|
||||||
|
if(Model._remoteHooks) {
|
||||||
|
Model._remoteHooks.emit('attached', app);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -65,7 +67,6 @@ app.models = function () {
|
||||||
return this._models;
|
return this._models;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all remote objects.
|
* Get all remote objects.
|
||||||
*/
|
*/
|
||||||
|
|
146
lib/asteroid.js
146
lib/asteroid.js
|
@ -4,11 +4,14 @@
|
||||||
|
|
||||||
var express = require('express')
|
var express = require('express')
|
||||||
, fs = require('fs')
|
, fs = require('fs')
|
||||||
|
, EventEmitter = require('events').EventEmitter
|
||||||
, path = require('path')
|
, path = require('path')
|
||||||
, proto = require('./application')
|
, proto = require('./application')
|
||||||
, utils = require('express/node_modules/connect').utils
|
, utils = require('express/node_modules/connect').utils
|
||||||
, DataSource = require('jugglingdb').DataSource
|
, DataSource = require('jugglingdb').DataSource
|
||||||
, ModelBuilder = require('jugglingdb').ModelBuilder;
|
, ModelBuilder = require('jugglingdb').ModelBuilder
|
||||||
|
, assert = require('assert')
|
||||||
|
, i8n = require('inflection');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expose `createApplication()`.
|
* Expose `createApplication()`.
|
||||||
|
@ -83,9 +86,52 @@ asteroid.errorHandler.title = 'Asteroid';
|
||||||
asteroid.createDataSource = function (name, options) {
|
asteroid.createDataSource = function (name, options) {
|
||||||
var ds = new DataSource(name, options);
|
var ds = new DataSource(name, options);
|
||||||
ds.createModel = function (name, properties, settings) {
|
ds.createModel = function (name, properties, settings) {
|
||||||
var Model = asteroid.createModel(name, properties, settings);
|
var ModelCtor = asteroid.createModel(name, properties, settings);
|
||||||
Model.attachTo(ds);
|
ModelCtor.attachTo(ds);
|
||||||
return Model;
|
|
||||||
|
var hasMany = ModelCtor.hasMany;
|
||||||
|
|
||||||
|
if(hasMany) {
|
||||||
|
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[methodName] cannot be a shared method
|
||||||
|
// because it is defined inside
|
||||||
|
// a property getter...
|
||||||
|
|
||||||
|
this[methodName].apply(thisClass, arguments);
|
||||||
|
};
|
||||||
|
|
||||||
|
fn.shared = true;
|
||||||
|
fn.http = {verb: 'get', path: '/' + methodName};
|
||||||
|
fn.accepts = {arg: 'where', type: 'object'};
|
||||||
|
hasMany.apply(this, arguments);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return ModelCtor;
|
||||||
}
|
}
|
||||||
return ds;
|
return ds;
|
||||||
}
|
}
|
||||||
|
@ -103,46 +149,6 @@ asteroid.createModel = function (name, properties, options) {
|
||||||
|
|
||||||
var mb = new ModelBuilder();
|
var mb = new ModelBuilder();
|
||||||
var ModelCtor = mb.define(name, properties, arguments);
|
var ModelCtor = mb.define(name, properties, arguments);
|
||||||
var hasMany = ModelCtor.hasMany;
|
|
||||||
|
|
||||||
if(hasMany) {
|
|
||||||
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
|
|
||||||
// inside a property getter...
|
|
||||||
|
|
||||||
this[methodName].apply(thisClass, arguments);
|
|
||||||
};
|
|
||||||
|
|
||||||
fn.shared = true;
|
|
||||||
fn.http = {verb: 'get', path: '/' + methodName};
|
|
||||||
hasMany.apply(this, arguments);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
ModelCtor.shared = true;
|
ModelCtor.shared = true;
|
||||||
ModelCtor.sharedCtor = function (data, id, fn) {
|
ModelCtor.sharedCtor = function (data, id, fn) {
|
||||||
|
@ -152,7 +158,13 @@ asteroid.createModel = function (name, properties, options) {
|
||||||
id = null;
|
id = null;
|
||||||
} else if (typeof id === 'function') {
|
} else if (typeof id === 'function') {
|
||||||
fn = id;
|
fn = id;
|
||||||
id = null;
|
|
||||||
|
if(typeof data !== 'object') {
|
||||||
|
id = data;
|
||||||
|
data = null;
|
||||||
|
} else {
|
||||||
|
id = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(id && data) {
|
if(id && data) {
|
||||||
|
@ -180,20 +192,39 @@ asteroid.createModel = function (name, properties, options) {
|
||||||
|
|
||||||
// before remote hook
|
// before remote hook
|
||||||
ModelCtor.beforeRemote = function (name, fn) {
|
ModelCtor.beforeRemote = function (name, fn) {
|
||||||
var remotes = this.app.remotes();
|
var self = this;
|
||||||
remotes.before(ModelCtor.pluralModelName + '.' + name, function (ctx, next) {
|
if(this.app) {
|
||||||
fn(ctx, ctx.instance, next);
|
var remotes = this.app.remotes();
|
||||||
});
|
remotes.before(self.pluralModelName + '.' + name, function (ctx, next) {
|
||||||
|
fn(ctx, ctx.instance, next);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
var args = arguments;
|
||||||
|
this._remoteHooks.once('attached', function () {
|
||||||
|
self.beforeRemote.apply(ModelCtor, args);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// after remote hook
|
// after remote hook
|
||||||
ModelCtor.afterRemote = function (name, fn) {
|
ModelCtor.afterRemote = function (name, fn) {
|
||||||
var remotes = this.app.remotes();
|
var self = this;
|
||||||
remotes.before(ModelCtor.pluralModelName + '.' + name, function (ctx, next) {
|
if(this.app) {
|
||||||
fn(ctx, ctx.instance, next);
|
var remotes = this.app.remotes();
|
||||||
});
|
remotes.after(self.pluralModelName + '.' + name, function (ctx, next) {
|
||||||
|
fn(ctx, ctx.instance, next);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
var args = arguments;
|
||||||
|
this._remoteHooks.once('attached', function () {
|
||||||
|
self.afterRemote.apply(ModelCtor, args);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// allow hooks to be added before attaching to an app
|
||||||
|
ModelCtor._remoteHooks = new EventEmitter();
|
||||||
|
|
||||||
return ModelCtor;
|
return ModelCtor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,8 +236,11 @@ asteroid.createModel = function (name, properties, options) {
|
||||||
|
|
||||||
asteroid.remoteMethod = function (fn, options) {
|
asteroid.remoteMethod = function (fn, options) {
|
||||||
fn.shared = true;
|
fn.shared = true;
|
||||||
Object.keys(options).forEach(function (key) {
|
if(typeof options === 'object') {
|
||||||
fn[key] = options[key];
|
Object.keys(options).forEach(function (key) {
|
||||||
});
|
fn[key] = options[key];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
fn.http = fn.http || {verb: 'get'};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue