2013-04-10 17:55:13 +00:00
|
|
|
/**
|
|
|
|
* Expose `Model`.
|
|
|
|
*/
|
|
|
|
|
|
|
|
module.exports = Model;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Module dependencies.
|
|
|
|
*/
|
|
|
|
|
2013-05-01 19:11:43 +00:00
|
|
|
var EventEmitter = require('events').EventEmitter
|
2013-04-10 17:55:13 +00:00
|
|
|
, debug = require('debug')('model')
|
|
|
|
, util = require('util')
|
|
|
|
, inherits = util.inherits
|
|
|
|
, assert = require('assert');
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Create a new `Model` with the given `options`.
|
|
|
|
*
|
|
|
|
* @param {Object} options
|
|
|
|
* @return {Model}
|
|
|
|
*/
|
|
|
|
|
2013-05-01 19:11:43 +00:00
|
|
|
function Model(data) {
|
|
|
|
EventEmitter.call(this);
|
|
|
|
|
|
|
|
var ModelCtor = this.constructor;
|
|
|
|
var schema = ModelCtor.schema;
|
|
|
|
|
|
|
|
// get properties that match the schema
|
|
|
|
var matchedProperties = schema.getMatchedProperties(data);
|
|
|
|
|
|
|
|
// set properties that match the schema
|
|
|
|
Object.keys(matchedProperties).forEach(function (property) {
|
|
|
|
this[property] = matchedProperties[property];
|
|
|
|
}.bind(this));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Inherit from `EventEmitter`.
|
|
|
|
*/
|
|
|
|
|
|
|
|
inherits(Model, EventEmitter);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Create a new Model class from the given options.
|
|
|
|
*
|
|
|
|
* @param options {Object}
|
|
|
|
* @return {Model}
|
|
|
|
*/
|
|
|
|
|
|
|
|
Model.extend = function (options) {
|
|
|
|
var Super = this;
|
|
|
|
|
|
|
|
// the new constructor
|
|
|
|
function Model() {
|
|
|
|
Super.apply(this, arguments);
|
|
|
|
}
|
2013-04-10 17:55:13 +00:00
|
|
|
|
2013-05-01 19:11:43 +00:00
|
|
|
Model.options = options;
|
2013-04-10 17:55:13 +00:00
|
|
|
|
2013-05-01 19:11:43 +00:00
|
|
|
assert(options.name, 'must provide a name when extending from model');
|
2013-04-10 17:55:13 +00:00
|
|
|
|
2013-05-01 19:11:43 +00:00
|
|
|
// model namespace
|
|
|
|
Model.namespace = options.name;
|
2013-04-10 17:55:13 +00:00
|
|
|
|
2013-05-01 19:11:43 +00:00
|
|
|
// define the remote namespace
|
|
|
|
Model.remoteNamespace = options.plural || pluralize(Model.namespace);
|
2013-04-10 17:55:13 +00:00
|
|
|
|
2013-05-01 19:11:43 +00:00
|
|
|
// inherit all static methods
|
|
|
|
Object.keys(Super).forEach(function (key) {
|
|
|
|
if(typeof Super[key] === 'function') {
|
|
|
|
MyModel[key] = Super[key];
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
// inherit all other things
|
|
|
|
inherits(MyModel, Super);
|
|
|
|
|
|
|
|
return Model;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Construct a model instance for remote use.
|
|
|
|
*/
|
|
|
|
|
|
|
|
Model.remoteConstructor = function (data, fn) {
|
|
|
|
var ModelCtor = this;
|
2013-04-10 17:55:13 +00:00
|
|
|
|
2013-05-01 19:11:43 +00:00
|
|
|
fn(null, new ModelCtor(data));
|
2013-04-10 17:55:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2013-05-01 19:11:43 +00:00
|
|
|
* Define the data the model represents using the data definition language.
|
2013-04-10 17:55:13 +00:00
|
|
|
*/
|
|
|
|
|
2013-05-01 19:11:43 +00:00
|
|
|
Model.defineSchema = function (schema) {
|
|
|
|
throw new Error('not implemented');
|
|
|
|
}
|
2013-04-10 17:55:13 +00:00
|
|
|
|
|
|
|
/**
|
2013-05-01 19:11:43 +00:00
|
|
|
* Set the data source for the model. Must provide a name of an existing data source.
|
|
|
|
* If the namespace is not provided the plural model name (eg. colors) will be used.
|
|
|
|
*
|
|
|
|
* **Note:** If you do not set a data source or a map (or both) the default data source
|
|
|
|
* will be used (an in memory database).
|
2013-04-10 17:55:13 +00:00
|
|
|
*/
|
|
|
|
|
2013-05-01 19:11:43 +00:00
|
|
|
Model.dataSource = function (dataSourceName, namespace) {
|
|
|
|
namespace = namespace || this.namespace;
|
|
|
|
throw new Error('not implemented');
|
|
|
|
}
|
2013-04-10 17:55:13 +00:00
|
|
|
|
2013-04-19 16:51:06 +00:00
|
|
|
/**
|
2013-05-01 19:11:43 +00:00
|
|
|
* Define a mapping between the data source representation of your data and your app's representation.
|
2013-04-19 16:51:06 +00:00
|
|
|
*/
|
|
|
|
|
2013-05-01 19:11:43 +00:00
|
|
|
Model.defineMap = function (mapping) {
|
|
|
|
// see: https://github.com/strongloop/asteroid/tree/master/node_modules/model#mymodeldefinemapmap
|
|
|
|
throw new Error('not implemented');
|
2013-04-19 16:51:06 +00:00
|
|
|
}
|
|
|
|
|
2013-04-10 17:55:13 +00:00
|
|
|
/**
|
2013-05-01 19:11:43 +00:00
|
|
|
* Using the mapped data source, try to discover the schema of a table or other namespace (url, collection, etc).
|
2013-04-10 17:55:13 +00:00
|
|
|
*/
|
|
|
|
|
2013-05-01 19:11:43 +00:00
|
|
|
Model.discoverSchema = function (fn) {
|
|
|
|
throw new Error('not implemented');
|
2013-04-10 17:55:13 +00:00
|
|
|
}
|
|
|
|
|
2013-05-01 19:11:43 +00:00
|
|
|
/**
|
|
|
|
* Fetch a model by id.
|
|
|
|
*/
|
|
|
|
|
|
|
|
Model.getById = function (id, fn) {
|
|
|
|
var ModelCtor = this;
|
|
|
|
var model = new ModelCtor({id: id});
|
|
|
|
|
|
|
|
model.fetch(fn);
|
|
|
|
}
|
|
|
|
Model.getById.remotable = true;
|
|
|
|
Model.getById.returns = [
|
|
|
|
{arg: 'model', 'type': 'this'}
|
|
|
|
];
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Fetch the model data and update the instance.
|
|
|
|
*
|
|
|
|
* **Note:** this is a remotable instance method.
|
|
|
|
*/
|
|
|
|
|
|
|
|
Model.prototype.fetch = function (fn) {
|
|
|
|
throw new Error('not implemented');
|
|
|
|
}
|
|
|
|
Model.prototype.fetch.remotable = true;
|
|
|
|
Model.prototype.fetch.returns = [
|
|
|
|
{arg: 'model', 'type': 'this'}
|
|
|
|
];
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Save the model data.
|
|
|
|
*
|
|
|
|
* **Note:** this is a remotable instance method.
|
|
|
|
*/
|
|
|
|
|
|
|
|
Model.prototype.save = function (fn) {
|
|
|
|
throw new Error('not implemented');
|
|
|
|
}
|
|
|
|
Model.prototype.save.remotable = true;
|
|
|
|
Model.prototype.save.returns = [
|
|
|
|
{arg: 'model', 'type': 'this'}
|
|
|
|
];
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Helper method for creating and saving models.
|
|
|
|
*/
|
|
|
|
|
|
|
|
Model.create = function (data, fn) {
|
|
|
|
var ModelCtor = this;
|
|
|
|
var model = new ModelCtor(data);
|
|
|
|
|
|
|
|
model.save(fn);
|
|
|
|
|
|
|
|
// for chaining
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Remove the model.
|
|
|
|
*
|
|
|
|
* **Note:** this is a remotable instance method.
|
|
|
|
*/
|
|
|
|
|
|
|
|
Model.prototype.destroy = function (fn) {
|
|
|
|
throw new Error('not implemented');
|
|
|
|
}
|
2013-05-01 21:36:14 +00:00
|
|
|
Model.prototype.destroy.remotable = true;
|
2013-05-01 19:11:43 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Find by id.
|
|
|
|
*
|
|
|
|
* **Note:** this is a remotable static method.
|
|
|
|
*/
|
|
|
|
|
|
|
|
Model.findById = function (id, fn) {
|
|
|
|
throw new Error('not implemented');
|
|
|
|
}
|
|
|
|
Model.findById.remotable = true;
|
|
|
|
Model.findById.accepts = [
|
|
|
|
{arg: 'id', type: 'Number'}
|
|
|
|
];
|
|
|
|
Model.findById.returns = [
|
|
|
|
{arg: 'model', type: 'this'}
|
|
|
|
];
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Find all models that match the given query.
|
|
|
|
*
|
|
|
|
* **Note:** this is a remotable static method.
|
|
|
|
*/
|
|
|
|
|
|
|
|
Model.all = function (query, fn) {
|
|
|
|
if(typeof query === 'function') {
|
|
|
|
fn = query;
|
|
|
|
query = undefined;
|
|
|
|
}
|
|
|
|
|
|
|
|
throw new Error('not implemented');
|
|
|
|
}
|
|
|
|
Model.all.remotable = true;
|
|
|
|
Model.all.accepts = [
|
|
|
|
{arg: 'query', type: 'Object', optional: true}
|
|
|
|
];
|
|
|
|
Model.all.returns = [
|
|
|
|
{arg: 'models', type: ['this']}
|
|
|
|
];
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Count all models that match the given filter.
|
|
|
|
*
|
|
|
|
* **Note:** this is a remotable static method.
|
|
|
|
*/
|
|
|
|
|
|
|
|
Model.count = function (query, fn) {
|
|
|
|
if(typeof query === 'function') {
|
|
|
|
fn = query;
|
|
|
|
query = undefined;
|
|
|
|
}
|
|
|
|
|
|
|
|
throw new Error('not implemented');
|
|
|
|
}
|
|
|
|
Model.all.remotable = true;
|
|
|
|
Model.all.accepts = [
|
|
|
|
{arg: 'query', type: 'Object', optional: true}
|
|
|
|
];
|
|
|
|
Model.all.returns = [
|
|
|
|
{arg: 'count', type: 'Number'}
|
|
|
|
];
|