Reformat the code

This commit is contained in:
Raymond Feng 2014-01-24 09:09:53 -08:00
parent 58a06272c3
commit 2b8c1ebaee
53 changed files with 8825 additions and 8792 deletions

View File

@ -4,12 +4,14 @@ var modelBuilder = new ModelBuilder();
var Post = modelBuilder.define('Post', { var Post = modelBuilder.define('Post', {
title: { type: String, length: 255 }, title: { type: String, length: 255 },
content: { type: ModelBuilder.Text }, content: { type: ModelBuilder.Text },
date: { type: Date, default: function () { return new Date;} }, date: { type: Date, default: function () {
return new Date();
} },
timestamp: { type: Number, default: Date.now }, timestamp: { type: Number, default: Date.now },
published: { type: Boolean, default: false, index: true } published: { type: Boolean, default: false, index: true }
}); });
// simplier way to describe model // simpler way to describe model
var User = modelBuilder.define('User', { var User = modelBuilder.define('User', {
name: String, name: String,
bio: ModelBuilder.Text, bio: ModelBuilder.Text,

View File

@ -55,8 +55,8 @@ var user2 = new User({name: 'Smith'});
user2.save(function (err) { user2.save(function (err) {
console.log(user2); console.log(user2);
var post = user2.posts.build({title: 'Hello world'}); var post = user2.posts.build({title: 'Hello world'});
post.save(function(err, data) { post.save(function (err, data) {
console.log(err ? err: data); console.log(err ? err : data);
}); });
}); });
@ -79,7 +79,7 @@ User.create({name: 'Ray'}, function (err, data) {
}); });
User.scope('minors', {age: {le: 16}}); User.scope('minors', {age: {le: 16}});
User.minors(function(err, kids) { User.minors(function (err, kids) {
console.log('Kids: ', kids); console.log('Kids: ', kids);
}); });
@ -87,10 +87,10 @@ var Article = ds.define('Article', {title: String});
var Tag = ds.define('Tag', {name: String}); var Tag = ds.define('Tag', {name: String});
Article.hasAndBelongsToMany('tags'); Article.hasAndBelongsToMany('tags');
Article.create(function(e, article) { Article.create(function (e, article) {
article.tags.create({name: 'popular'}, function (err, data) { article.tags.create({name: 'popular'}, function (err, data) {
Article.findOne(function(e, article) { Article.findOne(function (e, article) {
article.tags(function(e, tags) { article.tags(function (e, tags) {
console.log(tags); console.log(tags);
}); });
}); });

View File

@ -9,7 +9,7 @@ var path = require('path'),
*/ */
function loadSchemasSync(schemaFile, dataSource) { function loadSchemasSync(schemaFile, dataSource) {
// Set up the data source // Set up the data source
if(!dataSource) { if (!dataSource) {
dataSource = new DataSource('memory'); dataSource = new DataSource('memory');
} }

View File

@ -15,14 +15,18 @@ var User = modelBuilder.define('User', {
zipCode: String, zipCode: String,
country: String country: String
}, },
emails: [{ emails: [
{
label: String, label: String,
email: String email: String
}], }
],
friends: [String] friends: [String]
}); });
var user = new User({name: 'Joe', age: 20, address: {street: '123 Main St', 'city': 'San Jose', state: 'CA'}, var user = new User({name: 'Joe', age: 20, address: {street: '123 Main St', 'city': 'San Jose', state: 'CA'},
emails: [{label: 'work', email: 'xyz@sample.com'}], emails: [
{label: 'work', email: 'xyz@sample.com'}
],
friends: ['John', 'Mary']}); friends: ['John', 'Mary']});
console.log(user.toObject()); console.log(user.toObject());

View File

@ -24,15 +24,14 @@ Customer.create({name: 'John'}, function (err, customer) {
}); });
}); });
Customer.hasMany(Order, {as: 'orders', foreignKey: 'customerId'}); Customer.hasMany(Order, {as: 'orders', foreignKey: 'customerId'});
Customer.create({name: 'Ray'}, function (err, customer) { Customer.create({name: 'Ray'}, function (err, customer) {
Order.create({customerId: customer.id, orderDate: new Date()}, function (err, order) { Order.create({customerId: customer.id, orderDate: new Date()}, function (err, order) {
customer.orders(console.log); customer.orders(console.log);
customer.orders.create({orderDate: new Date()}, function(err, order) { customer.orders.create({orderDate: new Date()}, function (err, order) {
console.log(order); console.log(order);
Customer.include([customer], 'orders', function(err, results) { Customer.include([customer], 'orders', function (err, results) {
console.log('Results: ', results); console.log('Results: ', results);
}); });
customer.orders.findById('2', console.log); customer.orders.findById('2', console.log);
@ -41,7 +40,6 @@ Customer.create({name: 'Ray'}, function (err, customer) {
}); });
}); });
var Physician = ds.createModel('Physician', { var Physician = ds.createModel('Physician', {
name: String name: String
}); });
@ -72,7 +70,6 @@ Physician.create({name: 'Smith'}, function (err, physician) {
}); });
}); });
var Assembly = ds.createModel('Assembly', { var Assembly = ds.createModel('Assembly', {
name: String name: String
}); });
@ -86,7 +83,7 @@ Part.hasAndBelongsToMany(Assembly);
Assembly.create({name: 'car'}, function (err, assembly) { Assembly.create({name: 'car'}, function (err, assembly) {
Part.create({partNumber: 'engine'}, function (err, part) { Part.create({partNumber: 'engine'}, function (err, part) {
assembly.parts.add(part, function(err) { assembly.parts.add(part, function (err) {
assembly.parts(console.log); assembly.parts(console.log);
}); });

View File

@ -27,15 +27,14 @@ Connector.prototype.execute = function (command, params, callback) {
throw new Error('query method should be declared in connector'); throw new Error('query method should be declared in connector');
}; };
/** /**
* Look up the data source by model name * Look up the data source by model name
* @param {String} model The model name * @param {String} model The model name
* @returns {DataSource} The data source * @returns {DataSource} The data source
*/ */
Connector.prototype.getDataSource = function(model) { Connector.prototype.getDataSource = function (model) {
var m = this._models[model]; var m = this._models[model];
if(!m) { if (!m) {
console.trace('Model not found: ' + model); console.trace('Model not found: ' + model);
} }
return m && m.model.dataSource; return m && m.model.dataSource;
@ -59,7 +58,6 @@ Connector.prototype.idNames = function (model) {
return this.getDataSource(model).idNames(model); return this.getDataSource(model).idNames(model);
}; };
/** /**
* Get the id index (sequence number, starting from 1) * Get the id index (sequence number, starting from 1)
* @param {String} model The model name * @param {String} model The model name
@ -68,8 +66,8 @@ Connector.prototype.idNames = function (model) {
*/ */
Connector.prototype.id = function (model, prop) { Connector.prototype.id = function (model, prop) {
var p = this._models[model].properties[prop]; var p = this._models[model].properties[prop];
if(!p) { if (!p) {
console.trace('Property not found: ' + model +'.' + prop); console.trace('Property not found: ' + model + '.' + prop);
} }
return p.id; return p.id;
}; };
@ -109,7 +107,7 @@ Connector.prototype.disconnect = function disconnect(cb) {
* @returns {*} The id value * @returns {*} The id value
* *
*/ */
Connector.prototype.getIdValue = function(model, data) { Connector.prototype.getIdValue = function (model, data) {
return data && data[this.idName(model)]; return data && data[this.idName(model)];
}; };
@ -120,12 +118,16 @@ Connector.prototype.getIdValue = function(model, data) {
* @param {*} value The id value * @param {*} value The id value
* *
*/ */
Connector.prototype.setIdValue = function(model, data, value) { Connector.prototype.setIdValue = function (model, data, value) {
if(data) { if (data) {
data[this.idName(model)] = value; data[this.idName(model)] = value;
} }
}; };
Connector.prototype.getType = function () {
return this.type;
};

View File

@ -15,16 +15,22 @@ function CradleAdapter(client) {
function createdbif(client, callback) { function createdbif(client, callback) {
client.exists(function (err, exists) { client.exists(function (err, exists) {
if(err) callback(err); if (err) callback(err);
if (!exists) { client.create(function() { callback(); }); } if (!exists) {
else { callback(); } client.create(function () {
callback();
});
}
else {
callback();
}
}); });
} }
function naturalize(data, model) { function naturalize(data, model) {
data.nature = model; data.nature = model;
//TODO: maybe this is not a really good idea //TODO: maybe this is not a really good idea
if(data.date) data.date = data.date.toString(); if (data.date) data.date = data.date.toString();
return data; return data;
} }
function idealize(data) { function idealize(data) {
@ -36,13 +42,13 @@ function stringify(data) {
} }
function errorHandler(callback, func) { function errorHandler(callback, func) {
return function(err, res) { return function (err, res) {
if (err) { if (err) {
console.log('cradle', err); console.log('cradle', err);
callback(err); callback(err);
} else { } else {
if(func) { if (func) {
func(res, function(res) { func(res, function (res) {
callback(null, res); callback(null, res);
}); });
} else { } else {
@ -53,10 +59,10 @@ function errorHandler(callback, func) {
}; };
function synchronize(functions, args, callback) { function synchronize(functions, args, callback) {
if(functions.length === 0) callback(); if (functions.length === 0) callback();
if(functions.length > 0 && args.length === functions.length) { if (functions.length > 0 && args.length === functions.length) {
functions[0](args[0][0], args[0][1], function(err, res) { functions[0](args[0][0], args[0][1], function (err, res) {
if(err) callback(err); if (err) callback(err);
functions.splice(0, 1); functions.splice(0, 1);
args.splice(0, 1); args.splice(0, 1);
synchronize(functions, args, callback); synchronize(functions, args, callback);
@ -98,9 +104,9 @@ function literally(a, b) {
function filtering(res, model, filter, instance) { function filtering(res, model, filter, instance) {
if(model) { if (model) {
if(filter == null) filter = {}; if (filter == null) filter = {};
if(filter.where == null) filter.where = {}; if (filter.where == null) filter.where = {};
filter.where.nature = model; filter.where.nature = model;
} }
// do we need some filtration? // do we need some filtration?
@ -142,7 +148,7 @@ function filtering(res, model, filter, instance) {
/** /**
* Connection/Disconnection * Connection/Disconnection
*/ */
exports.initialize = function(dataSource, callback) { exports.initialize = function (dataSource, callback) {
if (!cradle) return; if (!cradle) return;
// when using cradle if we dont wait for the dataSource to be connected, the models fails to load correctly. // when using cradle if we dont wait for the dataSource to be connected, the models fails to load correctly.
@ -168,37 +174,37 @@ exports.initialize = function(dataSource, callback) {
dataSource.settings.database = database; dataSource.settings.database = database;
dataSource.settings.options = options; dataSource.settings.options = options;
} }
dataSource.client = new(cradle.Connection)(dataSource.settings.host, dataSource.settings.port,dataSource.settings.options).database(dataSource.settings.database); dataSource.client = new (cradle.Connection)(dataSource.settings.host, dataSource.settings.port, dataSource.settings.options).database(dataSource.settings.database);
createdbif( createdbif(
dataSource.client, dataSource.client,
errorHandler(callback, function() { errorHandler(callback, function () {
dataSource.connector = new CradleAdapter(dataSource.client); dataSource.connector = new CradleAdapter(dataSource.client);
process.nextTick(callback); process.nextTick(callback);
})); }));
}; };
CradleAdapter.prototype.disconnect = function() { CradleAdapter.prototype.disconnect = function () {
}; };
/** /**
* Write methods * Write methods
*/ */
CradleAdapter.prototype.define = function(descr) { CradleAdapter.prototype.define = function (descr) {
this._models[descr.model.modelName] = descr; this._models[descr.model.modelName] = descr;
}; };
CradleAdapter.prototype.create = function(model, data, callback) { CradleAdapter.prototype.create = function (model, data, callback) {
this.client.save( this.client.save(
stringify(data.id), stringify(data.id),
naturalize(data, model), naturalize(data, model),
errorHandler(callback, function(res, cb) { errorHandler(callback, function (res, cb) {
cb(res.id); cb(res.id);
}) })
); );
}; };
CradleAdapter.prototype.save = function(model, data, callback) { CradleAdapter.prototype.save = function (model, data, callback) {
this.client.save( this.client.save(
stringify(data.id), stringify(data.id),
naturalize(data, model), naturalize(data, model),
@ -206,21 +212,21 @@ CradleAdapter.prototype.save = function(model, data, callback) {
) )
}; };
CradleAdapter.prototype.updateAttributes = function(model, id, data, callback) { CradleAdapter.prototype.updateAttributes = function (model, id, data, callback) {
this.client.merge( this.client.merge(
stringify(id), stringify(id),
data, data,
errorHandler(callback, function(doc, cb) { errorHandler(callback, function (doc, cb) {
cb(idealize(doc)); cb(idealize(doc));
}) })
); );
}; };
CradleAdapter.prototype.updateOrCreate = function(model, data, callback) { CradleAdapter.prototype.updateOrCreate = function (model, data, callback) {
this.client.get( this.client.get(
stringify(data.id), stringify(data.id),
function (err, doc) { function (err, doc) {
if(err) { if (err) {
this.create(model, data, callback); this.create(model, data, callback);
} else { } else {
this.updateAttributes(model, data.id, data, callback); this.updateAttributes(model, data.id, data, callback);
@ -232,54 +238,55 @@ CradleAdapter.prototype.updateOrCreate = function(model, data, callback) {
/** /**
* Read methods * Read methods
*/ */
CradleAdapter.prototype.exists = function(model, id, callback) { CradleAdapter.prototype.exists = function (model, id, callback) {
this.client.get( this.client.get(
stringify(id), stringify(id),
errorHandler(callback, function(doc, cb) { errorHandler(callback, function (doc, cb) {
cb(!!doc); cb(!!doc);
}) })
); );
}; };
CradleAdapter.prototype.find = function(model, id, callback) { CradleAdapter.prototype.find = function (model, id, callback) {
this.client.get( this.client.get(
stringify(id), stringify(id),
errorHandler(callback, function(doc, cb) { errorHandler(callback, function (doc, cb) {
cb(idealize(doc)); cb(idealize(doc));
}) })
); );
}; };
CradleAdapter.prototype.count = function(model, callback, where) { CradleAdapter.prototype.count = function (model, callback, where) {
this.models( this.models(
model, model,
{where: where}, {where: where},
callback, callback,
function(docs, cb) { function (docs, cb) {
cb(docs.length); cb(docs.length);
} }
); );
}; };
CradleAdapter.prototype.models = function(model, filter, callback, func) { CradleAdapter.prototype.models = function (model, filter, callback, func) {
var limit = 200; var limit = 200;
var skip = 0; var skip = 0;
if (filter != null) { if (filter != null) {
limit = filter.limit || limit; limit = filter.limit || limit;
skip = filter.skip ||skip; skip = filter.skip || skip;
} }
var self = this; var self = this;
self.client.save('_design/'+model, { self.client.save('_design/' + model, {
views : { views: {
all : { all: {
map : 'function(doc) { if (doc.nature == "'+model+'") { emit(doc._id, doc); } }' map: 'function(doc) { if (doc.nature == "' + model + '") { emit(doc._id, doc); } }'
} }
} }
}, function() { }, function () {
self.client.view(model+'/all', {include_docs:true, limit:limit, skip:skip}, errorHandler(callback, function(res, cb) { self.client.view(model + '/all', {include_docs: true, limit: limit, skip: skip},
var docs = res.map(function(doc) { errorHandler(callback, function (res, cb) {
var docs = res.map(function (doc) {
return idealize(doc); return idealize(doc);
}); });
var filtered = filtering(docs, model, filter, this._models) var filtered = filtering(docs, model, filter, this._models)
@ -289,7 +296,7 @@ CradleAdapter.prototype.models = function(model, filter, callback, func) {
}); });
}; };
CradleAdapter.prototype.all = function(model, filter, callback) { CradleAdapter.prototype.all = function (model, filter, callback) {
this.models( this.models(
model, model,
filter, filter,
@ -300,7 +307,7 @@ CradleAdapter.prototype.all = function(model, filter, callback) {
/** /**
* Detroy methods * Detroy methods
*/ */
CradleAdapter.prototype.destroy = function(model, id, callback) { CradleAdapter.prototype.destroy = function (model, id, callback) {
this.client.remove( this.client.remove(
stringify(id), stringify(id),
function (err, doc) { function (err, doc) {
@ -309,23 +316,23 @@ CradleAdapter.prototype.destroy = function(model, id, callback) {
); );
}; };
CradleAdapter.prototype.destroyAll = function(model, callback) { CradleAdapter.prototype.destroyAll = function (model, callback) {
this.models( this.models(
model, model,
null, null,
callback, callback,
function(docs, cb) { function (docs, cb) {
var docIds = docs.map(function(doc) { var docIds = docs.map(function (doc) {
return doc.id; return doc.id;
}); });
this.client.get(docIds, function(err, res) { this.client.get(docIds, function (err, res) {
if(err) cb(err); if (err) cb(err);
var funcs = res.map(function(doc) { var funcs = res.map(function (doc) {
return this.client.remove.bind(this.client); return this.client.remove.bind(this.client);
}.bind(this)); }.bind(this));
var args = res.map(function(doc) { var args = res.map(function (doc) {
return [doc._id, doc._rev]; return [doc._id, doc._rev];
}); });

View File

@ -11,20 +11,21 @@ function WebService() {
WebService.prototype.installPostProcessor = function installPostProcessor(descr) { WebService.prototype.installPostProcessor = function installPostProcessor(descr) {
var dates = []; var dates = [];
Object.keys(descr.properties).forEach(function(column) { Object.keys(descr.properties).forEach(function (column) {
if (descr.properties[column].type.name === 'Date') { if (descr.properties[column].type.name === 'Date') {
dates.push(column); dates.push(column);
} }
}); });
var postProcessor = function(model) { var postProcessor = function (model) {
var max = dates.length; var max = dates.length;
for (var i = 0; i < max; i++) { for (var i = 0; i < max; i++) {
var column = dates[i]; var column = dates[i];
if (model[column]) { if (model[column]) {
model[column] = new Date(model[column]); model[column] = new Date(model[column]);
} }
}; }
;
}; };
descr.postProcessor = postProcessor; descr.postProcessor = postProcessor;
@ -32,7 +33,7 @@ WebService.prototype.installPostProcessor = function installPostProcessor(descr)
WebService.prototype.preProcess = function preProcess(data) { WebService.prototype.preProcess = function preProcess(data) {
var result = {}; var result = {};
Object.keys(data).forEach(function(key) { Object.keys(data).forEach(function (key) {
if (data[key] != null) { if (data[key] != null) {
result[key] = data[key]; result[key] = data[key];
} }
@ -55,7 +56,8 @@ WebService.prototype.postProcessMultiple = function postProcessMultiple(model, d
if (data[i]) { if (data[i]) {
postProcessor(data[i]); postProcessor(data[i]);
} }
}; }
;
} }
}; };

View File

@ -33,7 +33,7 @@ function Memory(m) {
util.inherits(Memory, Connector); util.inherits(Memory, Connector);
Memory.prototype.connect = function(callback) { Memory.prototype.connect = function (callback) {
if (this.isTransaction) { if (this.isTransaction) {
this.onTransactionExec = callback; this.onTransactionExec = callback;
} else { } else {
@ -52,13 +52,13 @@ Memory.prototype.create = function create(model, data, callback) {
// FIXME: [rfeng] We need to generate unique ids based on the id type // FIXME: [rfeng] We need to generate unique ids based on the id type
// FIXME: [rfeng] We don't support composite ids yet // FIXME: [rfeng] We don't support composite ids yet
var currentId = this.ids[model]; var currentId = this.ids[model];
if(currentId === undefined) { if (currentId === undefined) {
// First time // First time
this.ids[model] = 1; this.ids[model] = 1;
currentId = 1; currentId = 1;
} }
var id = this.getIdValue(model, data) || currentId; var id = this.getIdValue(model, data) || currentId;
if(id > currentId) { if (id > currentId) {
// If the id is passed in and the value is greater than the current id // If the id is passed in and the value is greater than the current id
currentId = id; currentId = id;
} }
@ -69,7 +69,7 @@ Memory.prototype.create = function create(model, data, callback) {
id = (props[idName] && props[idName].type && props[idName].type(id)) || id; id = (props[idName] && props[idName].type && props[idName].type(id)) || id;
this.setIdValue(model, data, id); this.setIdValue(model, data, id);
this.cache[model][id] = JSON.stringify(data); this.cache[model][id] = JSON.stringify(data);
process.nextTick(function() { process.nextTick(function () {
callback(null, id); callback(null, id);
}); });
}; };
@ -113,17 +113,17 @@ Memory.prototype.destroy = function destroy(model, id, callback) {
process.nextTick(callback); process.nextTick(callback);
}; };
Memory.prototype.fromDb = function(model, data) { Memory.prototype.fromDb = function (model, data) {
if (!data) return null; if (!data) return null;
data = JSON.parse(data); data = JSON.parse(data);
var props = this._models[model].properties; var props = this._models[model].properties;
for(var key in data) { for (var key in data) {
var val = data[key]; var val = data[key];
if (val === undefined || val === null) { if (val === undefined || val === null) {
continue; continue;
} }
if (props[key]) { if (props[key]) {
switch(props[key].type.name) { switch (props[key].type.name) {
case 'Date': case 'Date':
val = new Date(val.toString().replace(/GMT.*$/, 'GMT')); val = new Date(val.toString().replace(/GMT.*$/, 'GMT'));
break; break;
@ -168,7 +168,7 @@ Memory.prototype.all = function all(model, filter, callback) {
var nearFilter = geo.nearFilter(filter.where); var nearFilter = geo.nearFilter(filter.where);
// geo sorting // geo sorting
if(nearFilter) { if (nearFilter) {
nodes = geo.filter(nodes, nearFilter); nodes = geo.filter(nodes, nearFilter);
} }
@ -178,7 +178,7 @@ Memory.prototype.all = function all(model, filter, callback) {
} }
// field selection // field selection
if(filter.fields) { if (filter.fields) {
nodes = nodes.map(utils.selectFields(filter.fields)); nodes = nodes.map(utils.selectFields(filter.fields));
} }
@ -197,11 +197,11 @@ Memory.prototype.all = function all(model, filter, callback) {
}); });
function sorting(a, b) { function sorting(a, b) {
for (var i=0, l=this.length; i<l; i++) { for (var i = 0, l = this.length; i < l; i++) {
if (a[this[i].key] > b[this[i].key]) { if (a[this[i].key] > b[this[i].key]) {
return 1*this[i].reverse; return 1 * this[i].reverse;
} else if (a[this[i].key] < b[this[i].key]) { } else if (a[this[i].key] < b[this[i].key]) {
return -1*this[i].reverse; return -1 * this[i].reverse;
} }
} }
return 0; return 0;
@ -231,7 +231,7 @@ function applyFilter(filter) {
if (typeof value === 'undefined') return undefined; if (typeof value === 'undefined') return undefined;
if (typeof example === 'object') { if (typeof example === 'object') {
// ignore geo near filter // ignore geo near filter
if(example.near) return true; if (example.near) return true;
if (example.inq) { if (example.inq) {
if (!value) return false; if (!value) return false;
@ -241,10 +241,10 @@ function applyFilter(filter) {
return false; return false;
} }
if(isNum(example.gt) && example.gt < value) return true; if (isNum(example.gt) && example.gt < value) return true;
if(isNum(example.gte) && example.gte <= value) return true; if (isNum(example.gte) && example.gte <= value) return true;
if(isNum(example.lt) && example.lt > value) return true; if (isNum(example.lt) && example.lt > value) return true;
if(isNum(example.lte) && example.lte >= value) return true; if (isNum(example.lte) && example.lte >= value) return true;
} }
// not strict equality // not strict equality
return (example !== null ? example.toString() : example) == (value !== null ? value.toString() : value); return (example !== null ? example.toString() : example) == (value !== null ? value.toString() : value);
@ -256,7 +256,7 @@ function applyFilter(filter) {
} }
Memory.prototype.destroyAll = function destroyAll(model, where, callback) { Memory.prototype.destroyAll = function destroyAll(model, where, callback) {
if(!callback && 'function' === typeof where) { if (!callback && 'function' === typeof where) {
callback = where; callback = where;
where = undefined; where = undefined;
} }
@ -266,11 +266,11 @@ Memory.prototype.destroyAll = function destroyAll(model, where, callback) {
filter = applyFilter({where: where}); filter = applyFilter({where: where});
} }
Object.keys(cache).forEach(function (id) { Object.keys(cache).forEach(function (id) {
if(!filter || filter(this.fromDb(model, cache[id]))) { if (!filter || filter(this.fromDb(model, cache[id]))) {
delete cache[id]; delete cache[id];
} }
}.bind(this)); }.bind(this));
if(!where) { if (!where) {
this.cache[model] = {}; this.cache[model] = {};
} }
process.nextTick(callback); process.nextTick(callback);
@ -292,9 +292,9 @@ Memory.prototype.count = function count(model, callback, where) {
}; };
Memory.prototype.updateAttributes = function updateAttributes(model, id, data, cb) { Memory.prototype.updateAttributes = function updateAttributes(model, id, data, cb) {
if(!id) { if (!id) {
var err = new Error('You must provide an id when updating attributes!'); var err = new Error('You must provide an id when updating attributes!');
if(cb) { if (cb) {
return cb(err); return cb(err);
} else { } else {
throw err; throw err;
@ -307,7 +307,7 @@ Memory.prototype.updateAttributes = function updateAttributes(model, id, data, c
var modelAsString = cachedModels && this.cache[model][id]; var modelAsString = cachedModels && this.cache[model][id];
var modelData = modelAsString && JSON.parse(modelAsString); var modelData = modelAsString && JSON.parse(modelAsString);
if(modelData) { if (modelData) {
this.save(model, merge(modelData, data), cb); this.save(model, merge(modelData, data), cb);
} else { } else {
cb(new Error('Could not update attributes. Object with id ' + id + ' does not exist!')); cb(new Error('Could not update attributes. Object with id ' + id + ' does not exist!'));
@ -318,7 +318,7 @@ Memory.prototype.transaction = function () {
return new Memory(this); return new Memory(this);
}; };
Memory.prototype.exec = function(callback) { Memory.prototype.exec = function (callback) {
this.onTransactionExec(); this.onTransactionExec();
setTimeout(callback, 50); setTimeout(callback, 50);
}; };

View File

@ -190,6 +190,7 @@ Neo4j.prototype.updateIndexes = function updateIndexes(model, node, cb) {
done(); done();
var error = false; var error = false;
function done(err) { function done(err) {
error = error || err; error = error || err;
if (--wait === 0) { if (--wait === 0) {

View File

@ -19,7 +19,6 @@ var utils = require('./utils');
var fieldsToArray = utils.fieldsToArray; var fieldsToArray = utils.fieldsToArray;
var removeUndefined = utils.removeUndefined; var removeUndefined = utils.removeUndefined;
/** /**
* DAO class - base class for all persist objects * DAO class - base class for all persist objects
* provides **common API** to access any database connector. * provides **common API** to access any database connector.
@ -32,10 +31,10 @@ var removeUndefined = utils.removeUndefined;
* @param {Object} data - initial object data * @param {Object} data - initial object data
*/ */
function DataAccessObject() { function DataAccessObject() {
if(DataAccessObject._mixins) { if (DataAccessObject._mixins) {
var self = this; var self = this;
var args = arguments; var args = arguments;
DataAccessObject._mixins.forEach(function(m) { DataAccessObject._mixins.forEach(function (m) {
m.call(self, args); m.call(self, args);
}); });
} }
@ -51,17 +50,17 @@ function getIdValue(m, data) {
} }
function setIdValue(m, data, value) { function setIdValue(m, data, value) {
if(data) { if (data) {
data[idName(m)] = value; data[idName(m)] = value;
} }
} }
DataAccessObject._forDB = function (data) { DataAccessObject._forDB = function (data) {
if(!(this.getDataSource().isRelational && this.getDataSource().isRelational())) { if (!(this.getDataSource().isRelational && this.getDataSource().isRelational())) {
return data; return data;
} }
var res = {}; var res = {};
for(var propName in data) { for (var propName in data) {
var type = this.getPropertyType(propName); var type = this.getPropertyType(propName);
if (type === 'JSON' || type === 'Any' || type === 'Object' || data[propName] instanceof Array) { if (type === 'JSON' || type === 'Any' || type === 'Object' || data[propName] instanceof Array) {
res[propName] = JSON.stringify(data[propName]); res[propName] = JSON.stringify(data[propName]);
@ -94,7 +93,8 @@ DataAccessObject.create = function (data, callback) {
} }
if (typeof callback !== 'function') { if (typeof callback !== 'function') {
callback = function () {}; callback = function () {
};
} }
if (!data) { if (!data) {
@ -110,8 +110,8 @@ DataAccessObject.create = function (data, callback) {
var instances = []; var instances = [];
for (var i = 0; i < data.length; i += 1) { for (var i = 0; i < data.length; i += 1) {
(function(d, i) { (function (d, i) {
instances.push(Model.create(d, function(err, inst) { instances.push(Model.create(d, function (err, inst) {
if (err) { if (err) {
errors[i] = err; errors[i] = err;
gotError = true; gotError = true;
@ -130,7 +130,6 @@ DataAccessObject.create = function (data, callback) {
} }
} }
var obj; var obj;
// if we come from save // if we come from save
if (data instanceof Model && !getIdValue(this, data)) { if (data instanceof Model && !getIdValue(this, data)) {
@ -141,7 +140,7 @@ DataAccessObject.create = function (data, callback) {
data = obj.toObject(true); data = obj.toObject(true);
// validation required // validation required
obj.isValid(function(valid) { obj.isValid(function (valid) {
if (valid) { if (valid) {
create(); create();
} else { } else {
@ -150,8 +149,8 @@ DataAccessObject.create = function (data, callback) {
}, data); }, data);
function create() { function create() {
obj.trigger('create', function(createDone) { obj.trigger('create', function (createDone) {
obj.trigger('save', function(saveDone) { obj.trigger('save', function (saveDone) {
var _idName = idName(Model); var _idName = idName(Model);
this._adapter().create(modelName, this.constructor._forDB(obj.toObject(true)), function (err, id, rev) { this._adapter().create(modelName, this.constructor._forDB(obj.toObject(true)), function (err, id, rev) {
@ -188,8 +187,8 @@ DataAccessObject.create = function (data, callback) {
*/ */
function setRemoting(fn, options) { function setRemoting(fn, options) {
options = options || {}; options = options || {};
for(var opt in options) { for (var opt in options) {
if(options.hasOwnProperty(opt)) { if (options.hasOwnProperty(opt)) {
fn[opt] = options[opt]; fn[opt] = options[opt];
} }
} }
@ -250,7 +249,6 @@ setRemoting(DataAccessObject.upsert, {
http: {verb: 'put', path: '/'} http: {verb: 'put', path: '/'}
}); });
/** /**
* Find one record, same as `all`, limited by 1 and return object, not collection, * Find one record, same as `all`, limited by 1 and return object, not collection,
* if not found, create using data provided as second argument * if not found, create using data provided as second argument
@ -268,7 +266,8 @@ DataAccessObject.findOrCreate = function findOrCreate(query, data, callback) {
data = query && query.where; data = query && query.where;
} }
if (typeof callback === 'undefined') { if (typeof callback === 'undefined') {
callback = function () {}; callback = function () {
};
} }
var t = this; var t = this;
@ -383,22 +382,22 @@ DataAccessObject._coerce = function (where) {
return new OrigDate(arg); return new OrigDate(arg);
}; };
} else if (DataType === Boolean) { } else if (DataType === Boolean) {
DataType = function(val) { DataType = function (val) {
if(val === 'true') { if (val === 'true') {
return true; return true;
} else if(val === 'false') { } else if (val === 'false') {
return false; return false;
} else { } else {
return Boolean(val); return Boolean(val);
} }
}; };
} else if(DataType === Number) { } else if (DataType === Number) {
// This fixes a regression in mongodb connector // This fixes a regression in mongodb connector
// For numbers, only convert it produces a valid number // For numbers, only convert it produces a valid number
// LoopBack by default injects a number id. We should fix it based // LoopBack by default injects a number id. We should fix it based
// on the connector's input, for example, MongoDB should use string // on the connector's input, for example, MongoDB should use string
// while RDBs typically use number // while RDBs typically use number
DataType = function(val) { DataType = function (val) {
var num = Number(val); var num = Number(val);
return !isNaN(num) ? num : val; return !isNaN(num) ? num : val;
}; };
@ -418,7 +417,7 @@ DataAccessObject._coerce = function (where) {
} }
var val = where[p]; var val = where[p];
if(val === null || val === undefined) { if (val === null || val === undefined) {
continue; continue;
} }
// Check there is an operator // Check there is an operator
@ -485,7 +484,7 @@ DataAccessObject.find = function find(params, cb) {
params = params || {}; params = params || {};
if(params.where) { if (params.where) {
params.where = this._coerce(params.where); params.where = this._coerce(params.where);
} }
@ -494,25 +493,25 @@ DataAccessObject.find = function find(params, cb) {
var supportsGeo = !!this.getDataSource().connector.buildNearFilter; var supportsGeo = !!this.getDataSource().connector.buildNearFilter;
// normalize fields as array of included property names // normalize fields as array of included property names
if(fields) { if (fields) {
params.fields = fieldsToArray(fields, Object.keys(this.definition.properties)); params.fields = fieldsToArray(fields, Object.keys(this.definition.properties));
} }
params = removeUndefined(params); params = removeUndefined(params);
if(near) { if (near) {
if(supportsGeo) { if (supportsGeo) {
// convert it // convert it
this.getDataSource().connector.buildNearFilter(params, near); this.getDataSource().connector.buildNearFilter(params, near);
} else if(params.where) { } else if (params.where) {
// do in memory query // do in memory query
// using all documents // using all documents
this.getDataSource().connector.all(this.modelName, {}, function (err, data) { this.getDataSource().connector.all(this.modelName, {}, function (err, data) {
var memory = new Memory(); var memory = new Memory();
var modelName = constr.modelName; var modelName = constr.modelName;
if(err) { if (err) {
cb(err); cb(err);
} else if(Array.isArray(data)) { } else if (Array.isArray(data)) {
memory.define({ memory.define({
properties: constr.dataSource.definitions[constr.modelName].properties, properties: constr.dataSource.definitions[constr.modelName].properties,
settings: constr.dataSource.definitions[constr.modelName].settings, settings: constr.dataSource.definitions[constr.modelName].settings,
@ -552,7 +551,7 @@ DataAccessObject.find = function find(params, cb) {
if (data && data.countBeforeLimit) { if (data && data.countBeforeLimit) {
data.countBeforeLimit = data.countBeforeLimit; data.countBeforeLimit = data.countBeforeLimit;
} }
if(!supportsGeo && near) { if (!supportsGeo && near) {
data = geo.filter(data, near); data = geo.filter(data, near);
} }
@ -599,22 +598,21 @@ setRemoting(DataAccessObject.findOne, {
http: {verb: 'get', path: '/findOne'} http: {verb: 'get', path: '/findOne'}
}); });
/** /**
* Destroy all matching records * Destroy all matching records
* @param {Object} [where] An object that defines the criteria * @param {Object} [where] An object that defines the criteria
* @param {Function} [cb] - callback called with (err) * @param {Function} [cb] - callback called with (err)
*/ */
DataAccessObject.remove = DataAccessObject.remove =
DataAccessObject.deleteAll = DataAccessObject.deleteAll =
DataAccessObject.destroyAll = function destroyAll(where, cb) { DataAccessObject.destroyAll = function destroyAll(where, cb) {
if (stillConnecting(this.getDataSource(), this, arguments)) return; if (stillConnecting(this.getDataSource(), this, arguments)) return;
if(!cb && 'function' === typeof where) { if (!cb && 'function' === typeof where) {
cb = where; cb = where;
where = undefined; where = undefined;
} }
if(!where) { if (!where) {
this.getDataSource().connector.destroyAll(this.modelName, function (err, data) { this.getDataSource().connector.destroyAll(this.modelName, function (err, data) {
cb && cb(err, data); cb && cb(err, data);
}.bind(this)); }.bind(this));
@ -626,7 +624,7 @@ DataAccessObject.destroyAll = function destroyAll(where, cb) {
cb && cb(err, data); cb && cb(err, data);
}.bind(this)); }.bind(this));
} }
}; };
/** /**
* Destroy a record by id * Destroy a record by id
@ -634,7 +632,7 @@ DataAccessObject.destroyAll = function destroyAll(where, cb) {
* @param {Function} cb - callback called with (err) * @param {Function} cb - callback called with (err)
*/ */
DataAccessObject.removeById = DataAccessObject.removeById =
DataAccessObject.deleteById = DataAccessObject.deleteById =
DataAccessObject.destroyById = function deleteById(id, cb) { DataAccessObject.destroyById = function deleteById(id, cb) {
if (stillConnecting(this.getDataSource(), this, arguments)) return; if (stillConnecting(this.getDataSource(), this, arguments)) return;
@ -652,7 +650,6 @@ setRemoting(DataAccessObject.deleteById, {
http: {verb: 'del', path: '/:id'} http: {verb: 'del', path: '/:id'}
}); });
/** /**
* Return count of matched records * Return count of matched records
* *
@ -671,7 +668,6 @@ DataAccessObject.count = function (where, cb) {
this.getDataSource().connector.count(this.modelName, cb, where); this.getDataSource().connector.count(this.modelName, cb, where);
}; };
// count ~ remoting attributes // count ~ remoting attributes
setRemoting(DataAccessObject.count, { setRemoting(DataAccessObject.count, {
description: 'Count instances of the model matched by where from the data source', description: 'Count instances of the model matched by where from the data source',
@ -680,7 +676,6 @@ setRemoting(DataAccessObject.count, {
http: {verb: 'get', path: '/count'} http: {verb: 'get', path: '/count'}
}); });
/** /**
* Save instance. When instance haven't id, create method called instead. * Save instance. When instance haven't id, create method called instead.
* Triggers: validate, save, update | create * Triggers: validate, save, update | create
@ -695,7 +690,8 @@ DataAccessObject.prototype.save = function (options, callback) {
options = {}; options = {};
} }
callback = callback || function () {}; callback = callback || function () {
};
options = options || {}; options = options || {};
if (!('validate' in options)) { if (!('validate' in options)) {
@ -752,7 +748,6 @@ DataAccessObject.prototype.save = function (options, callback) {
} }
}; };
DataAccessObject.prototype.isNewRecord = function () { DataAccessObject.prototype.isNewRecord = function () {
return !getIdValue(this.constructor, this); return !getIdValue(this.constructor, this);
}; };
@ -771,8 +766,8 @@ DataAccessObject.prototype._adapter = function () {
* @triggers `destroy` hook (async) before and after destroying object * @triggers `destroy` hook (async) before and after destroying object
*/ */
DataAccessObject.prototype.remove = DataAccessObject.prototype.remove =
DataAccessObject.prototype.delete = DataAccessObject.prototype.delete =
DataAccessObject.prototype.destroy = function (cb) { DataAccessObject.prototype.destroy = function (cb) {
if (stillConnecting(this.getDataSource(), this, arguments)) return; if (stillConnecting(this.getDataSource(), this, arguments)) return;
this.trigger('destroy', function (destroyed) { this.trigger('destroy', function (destroyed) {
@ -782,12 +777,11 @@ DataAccessObject.prototype.destroy = function (cb) {
} }
destroyed(function () { destroyed(function () {
if(cb) cb(); if (cb) cb();
}); });
}.bind(this)); }.bind(this));
}); });
}; };
/** /**
* Update single attribute * Update single attribute
@ -829,7 +823,7 @@ DataAccessObject.prototype.updateAttributes = function updateAttributes(data, cb
} }
// update instance's properties // update instance's properties
for(var key in data) { for (var key in data) {
inst[key] = data[key]; inst[key] = data[key];
} }
@ -842,16 +836,17 @@ DataAccessObject.prototype.updateAttributes = function updateAttributes(data, cb
inst.trigger('save', function (saveDone) { inst.trigger('save', function (saveDone) {
inst.trigger('update', function (done) { inst.trigger('update', function (done) {
for(var key in data) { for (var key in data) {
inst[key] = data[key]; inst[key] = data[key];
} }
inst._adapter().updateAttributes(model, getIdValue(inst.constructor, inst), inst.constructor._forDB(data), function (err) { inst._adapter().updateAttributes(model, getIdValue(inst.constructor, inst), inst.constructor._forDB(data), function (err) {
if (!err) { if (!err) {
// update $was attrs // update $was attrs
for(var key in data) { for (var key in data) {
inst.__dataWas[key] = inst.__data[key]; inst.__dataWas[key] = inst.__data[key];
}; }
;
} }
done.call(inst, function () { done.call(inst, function () {
saveDone.call(inst, function () { saveDone.call(inst, function () {
@ -873,7 +868,6 @@ setRemoting(DataAccessObject.prototype.updateAttributes, {
http: {verb: 'put', path: '/'} http: {verb: 'put', path: '/'}
}); });
/** /**
* Reload object from persistence * Reload object from persistence
* *
@ -887,11 +881,11 @@ DataAccessObject.prototype.reload = function reload(callback) {
}; };
/* /*
setRemoting(DataAccessObject.prototype.reload, { setRemoting(DataAccessObject.prototype.reload, {
description: 'Reload a model instance from the data source', description: 'Reload a model instance from the data source',
returns: {arg: 'data', type: 'object', root: true} returns: {arg: 'data', type: 'object', root: true}
}); });
*/ */
/** /**
* Define readonly property on object * Define readonly property on object

View File

@ -15,8 +15,6 @@ var fs = require('fs');
var assert = require('assert'); var assert = require('assert');
var async = require('async'); var async = require('async');
var existsSync = fs.existsSync || path.existsSync;
/** /**
* Export public API * Export public API
*/ */
@ -65,12 +63,12 @@ function DataSource(name, settings, modelBuilder) {
} }
// Check if the first argument is a URL // Check if the first argument is a URL
if(typeof name === 'string' && name.indexOf('://') !== -1 ) { if (typeof name === 'string' && name.indexOf('://') !== -1) {
name = utils.parseSettings(name); name = utils.parseSettings(name);
} }
// Check if the settings is in the form of URL string // Check if the settings is in the form of URL string
if(typeof settings === 'string' && settings.indexOf('://') !== -1 ) { if (typeof settings === 'string' && settings.indexOf('://') !== -1) {
settings = utils.parseSettings(settings); settings = utils.parseSettings(settings);
} }
@ -91,14 +89,15 @@ function DataSource(name, settings, modelBuilder) {
// DataAccessObject - connector defined or supply the default // DataAccessObject - connector defined or supply the default
var dao = (connector && connector.DataAccessObject) || this.constructor.DataAccessObject; var dao = (connector && connector.DataAccessObject) || this.constructor.DataAccessObject;
this.DataAccessObject = function() {}; this.DataAccessObject = function () {
};
// define DataAccessObject methods // define DataAccessObject methods
Object.keys(dao).forEach(function (name) { Object.keys(dao).forEach(function (name) {
var fn = dao[name]; var fn = dao[name];
this.DataAccessObject[name] = fn; this.DataAccessObject[name] = fn;
if(typeof fn === 'function') { if (typeof fn === 'function') {
this.defineOperation(name, { this.defineOperation(name, {
accepts: fn.accepts, accepts: fn.accepts,
'returns': fn.returns, 'returns': fn.returns,
@ -114,7 +113,7 @@ function DataSource(name, settings, modelBuilder) {
Object.keys(dao.prototype).forEach(function (name) { Object.keys(dao.prototype).forEach(function (name) {
var fn = dao.prototype[name]; var fn = dao.prototype[name];
this.DataAccessObject.prototype[name] = fn; this.DataAccessObject.prototype[name] = fn;
if(typeof fn === 'function') { if (typeof fn === 'function') {
this.defineOperation(name, { this.defineOperation(name, {
prototype: true, prototype: true,
accepts: fn.accepts, accepts: fn.accepts,
@ -129,15 +128,11 @@ function DataSource(name, settings, modelBuilder) {
} }
util.inherits(DataSource, EventEmitter); util.inherits(DataSource, EventEmitter);
// allow child classes to supply a data access object // allow child classes to supply a data access object
DataSource.DataAccessObject = DataAccessObject; DataSource.DataAccessObject = DataAccessObject;
/** /**
* Set up the connector instance for backward compatibility with JugglingDB schema/adapter * Set up the connector instance for backward compatibility with JugglingDB schema/adapter
* @private * @private
@ -181,7 +176,7 @@ function connectorModuleNames(name) {
function tryModules(names, loader) { function tryModules(names, loader) {
var mod; var mod;
loader = loader || require; loader = loader || require;
for(var m =0; m<names.length; m++) { for (var m = 0; m < names.length; m++) {
try { try {
mod = loader(names[m]); mod = loader(names[m]);
} catch (e) { } catch (e) {
@ -200,11 +195,11 @@ function tryModules(names, loader) {
* @returns {*} * @returns {*}
* @private * @private
*/ */
DataSource._resolveConnector = function(name, loader) { DataSource._resolveConnector = function (name, loader) {
var names = connectorModuleNames(name); var names = connectorModuleNames(name);
var connector = tryModules(names , loader); var connector = tryModules(names, loader);
var error = null; var error = null;
if(!connector) { if (!connector) {
error = '\nWARNING: LoopBack connector "' + name error = '\nWARNING: LoopBack connector "' + name
+ '" is not installed at any of the locations ' + names + '" is not installed at any of the locations ' + names
+ '. To fix, run:\n\n npm install ' + '. To fix, run:\n\n npm install '
@ -223,22 +218,22 @@ DataSource._resolveConnector = function(name, loader) {
* @returns {*} * @returns {*}
* @private * @private
*/ */
DataSource.prototype.setup = function(name, settings) { DataSource.prototype.setup = function (name, settings) {
var dataSource = this; var dataSource = this;
var connector; var connector;
// support single settings object // support single settings object
if(name && typeof name === 'object' && !settings) { if (name && typeof name === 'object' && !settings) {
settings = name; settings = name;
name = undefined; name = undefined;
} }
if(typeof settings === 'object') { if (typeof settings === 'object') {
if(settings.initialize) { if (settings.initialize) {
connector = settings; connector = settings;
} else if(settings.connector) { } else if (settings.connector) {
connector = settings.connector; connector = settings.connector;
} else if(settings.adapter) { } else if (settings.adapter) {
connector = settings.adapter; connector = settings.adapter;
} }
} }
@ -249,7 +244,7 @@ DataSource.prototype.setup = function(name, settings) {
// Check the debug env settings // Check the debug env settings
var debugEnv = process.env.DEBUG || process.env.NODE_DEBUG || ''; var debugEnv = process.env.DEBUG || process.env.NODE_DEBUG || '';
var debugModules = debugEnv.split(/[\s,]+/); var debugModules = debugEnv.split(/[\s,]+/);
if(debugModules.indexOf('loopback') !== -1) { if (debugModules.indexOf('loopback') !== -1) {
this.settings.debug = true; this.settings.debug = true;
} }
@ -257,7 +252,7 @@ DataSource.prototype.setup = function(name, settings) {
this.connected = false; this.connected = false;
this.connecting = false; this.connecting = false;
if(typeof connector === 'string') { if (typeof connector === 'string') {
name = connector; name = connector;
connector = undefined; connector = undefined;
} }
@ -273,7 +268,7 @@ DataSource.prototype.setup = function(name, settings) {
// The connector has not been resolved // The connector has not been resolved
var result = DataSource._resolveConnector(name); var result = DataSource._resolveConnector(name);
connector = result.connector; connector = result.connector;
if(!connector) { if (!connector) {
console.error(result.error); console.error(result.error);
return; return;
} }
@ -289,7 +284,7 @@ DataSource.prototype.setup = function(name, settings) {
throw new Error('Connector is not defined correctly: it should create `connector` member of dataSource'); throw new Error('Connector is not defined correctly: it should create `connector` member of dataSource');
} }
this.connected = !err; // Connected now this.connected = !err; // Connected now
if(this.connected) { if (this.connected) {
this.emit('connected'); this.emit('connected');
} else { } else {
// The connection fails, let's report it and hope it will be recovered in the next call // The connection fails, let's report it and hope it will be recovered in the next call
@ -302,24 +297,24 @@ DataSource.prototype.setup = function(name, settings) {
if ('function' === typeof connector.initialize) { if ('function' === typeof connector.initialize) {
// Call the async initialize method // Call the async initialize method
connector.initialize(this, postInit); connector.initialize(this, postInit);
} else if('function' === typeof connector) { } else if ('function' === typeof connector) {
// Use the connector constructor directly // Use the connector constructor directly
this.connector = new connector(this.settings); this.connector = new connector(this.settings);
postInit(); postInit();
} }
} }
dataSource.connect = function(cb) { dataSource.connect = function (cb) {
var dataSource = this; var dataSource = this;
if(dataSource.connected || dataSource.connecting) { if (dataSource.connected || dataSource.connecting) {
process.nextTick(function() { process.nextTick(function () {
cb && cb(); cb && cb();
}); });
return; return;
} }
dataSource.connecting = true; dataSource.connecting = true;
if (dataSource.connector.connect) { if (dataSource.connector.connect) {
dataSource.connector.connect(function(err, result) { dataSource.connector.connect(function (err, result) {
if (!err) { if (!err) {
dataSource.connected = true; dataSource.connected = true;
dataSource.connecting = false; dataSource.connecting = false;
@ -332,7 +327,7 @@ DataSource.prototype.setup = function(name, settings) {
cb && cb(err, result); cb && cb(err, result);
}); });
} else { } else {
process.nextTick(function() { process.nextTick(function () {
dataSource.connected = true; dataSource.connected = true;
dataSource.connecting = false; dataSource.connecting = false;
dataSource.emit('connected'); dataSource.emit('connected');
@ -343,7 +338,7 @@ DataSource.prototype.setup = function(name, settings) {
}; };
function isModelClass(cls) { function isModelClass(cls) {
if(!cls) { if (!cls) {
return false; return false;
} }
return cls.prototype instanceof ModelBaseClass; return cls.prototype instanceof ModelBaseClass;
@ -351,7 +346,6 @@ function isModelClass(cls) {
DataSource.relationTypes = ['belongsTo', 'hasMany', 'hasAndBelongsToMany']; DataSource.relationTypes = ['belongsTo', 'hasMany', 'hasAndBelongsToMany'];
function isModelDataSourceAttached(model) { function isModelDataSourceAttached(model) {
return model && (!model.settings.unresolved) && (model.dataSource instanceof DataSource); return model && (!model.settings.unresolved) && (model.dataSource instanceof DataSource);
} }
@ -360,7 +354,7 @@ function isModelDataSourceAttached(model) {
* @param modelClass * @param modelClass
* @param relations * @param relations
*/ */
DataSource.prototype.defineRelations = function(modelClass, relations) { DataSource.prototype.defineRelations = function (modelClass, relations) {
// Create a function for the closure in the loop // Create a function for the closure in the loop
var createListener = function (name, relation, targetModel, throughModel) { var createListener = function (name, relation, targetModel, throughModel) {
@ -501,12 +495,12 @@ DataSource.prototype.createModel = DataSource.prototype.define = function define
properties = properties || {}; properties = properties || {};
settings = settings || {}; settings = settings || {};
if(this.isRelational()) { if (this.isRelational()) {
// Set the strict mode to be true for relational DBs by default // Set the strict mode to be true for relational DBs by default
if(settings.strict === undefined || settings.strict === null) { if (settings.strict === undefined || settings.strict === null) {
settings.strict = true; settings.strict = true;
} }
if(settings.strict === false) { if (settings.strict === false) {
settings.strict = 'throw'; settings.strict = 'throw';
} }
} }
@ -514,7 +508,7 @@ DataSource.prototype.createModel = DataSource.prototype.define = function define
var modelClass = this.modelBuilder.define(className, properties, settings); var modelClass = this.modelBuilder.define(className, properties, settings);
modelClass.dataSource = this; modelClass.dataSource = this;
if(settings.unresolved) { if (settings.unresolved) {
return modelClass; return modelClass;
} }
@ -524,7 +518,6 @@ DataSource.prototype.createModel = DataSource.prototype.define = function define
return modelClass; return modelClass;
}; };
/** /**
* Mixin DataAccessObject methods. * Mixin DataAccessObject methods.
* *
@ -536,14 +529,14 @@ DataSource.prototype.mixin = function (ModelCtor) {
var DAO = this.DataAccessObject; var DAO = this.DataAccessObject;
// mixin DAO // mixin DAO
jutil.mixin(ModelCtor, DAO, {proxyFunctions : true}); jutil.mixin(ModelCtor, DAO, {proxyFunctions: true});
// decorate operations as alias functions // decorate operations as alias functions
Object.keys(ops).forEach(function (name) { Object.keys(ops).forEach(function (name) {
var op = ops[name]; var op = ops[name];
var scope; var scope;
if(op.enabled) { if (op.enabled) {
scope = op.prototype ? ModelCtor.prototype : ModelCtor; scope = op.prototype ? ModelCtor.prototype : ModelCtor;
// var sfn = scope[name] = function () { // var sfn = scope[name] = function () {
// op.scope[op.fnName].apply(self, arguments); // op.scope[op.fnName].apply(self, arguments);
@ -551,14 +544,14 @@ DataSource.prototype.mixin = function (ModelCtor) {
Object.keys(op) Object.keys(op)
.filter(function (key) { .filter(function (key) {
// filter out the following keys // filter out the following keys
return ~ [ return ~[
'scope', 'scope',
'fnName', 'fnName',
'prototype' 'prototype'
].indexOf(key); ].indexOf(key);
}) })
.forEach(function (key) { .forEach(function (key) {
if(typeof op[key] !== 'undefined') { if (typeof op[key] !== 'undefined') {
op.scope[op.fnName][key] = op[key]; op.scope[op.fnName][key] = op[key];
} }
}); });
@ -566,11 +559,11 @@ DataSource.prototype.mixin = function (ModelCtor) {
}); });
}; };
DataSource.prototype.getModel = function(name, forceCreate) { DataSource.prototype.getModel = function (name, forceCreate) {
return this.modelBuilder.getModel(name, forceCreate); return this.modelBuilder.getModel(name, forceCreate);
}; };
DataSource.prototype.getModelDefinition = function(name) { DataSource.prototype.getModelDefinition = function (name) {
return this.modelBuilder.getModelDefinition(name); return this.modelBuilder.getModelDefinition(name);
}; };
@ -581,12 +574,12 @@ DataSource.prototype.getModelDefinition = function(name) {
*/ */
DataSource.prototype.attach = function (modelClass) { DataSource.prototype.attach = function (modelClass) {
if(modelClass.dataSource === this) { if (modelClass.dataSource === this) {
// Already attached to the data source // Already attached to the data source
return modelClass; return modelClass;
} }
if(modelClass.modelBuilder !== this.modelBuilder) { if (modelClass.modelBuilder !== this.modelBuilder) {
this.modelBuilder.definitions[modelClass.modelName] = modelClass.definition; this.modelBuilder.definitions[modelClass.modelName] = modelClass.definition;
this.modelBuilder.models[modelClass.modelName] = modelClass; this.modelBuilder.models[modelClass.modelName] = modelClass;
// reset the modelBuilder // reset the modelBuilder
@ -684,7 +677,6 @@ DataSource.prototype.discoverModelDefinitions = function (options, cb) {
} }
}; };
/** /**
* The synchronous version of discoverModelDefinitions * The synchronous version of discoverModelDefinitions
* @param {Object} options The options * @param {Object} options The options
@ -765,7 +757,7 @@ DataSource.prototype.discoverModelPropertiesSync = function (modelName, options)
* @param {Object} options The options * @param {Object} options The options
* @param {Function} [cb] The callback function * @param {Function} [cb] The callback function
*/ */
DataSource.prototype.discoverPrimaryKeys= function(modelName, options, cb) { DataSource.prototype.discoverPrimaryKeys = function (modelName, options, cb) {
this.freeze(); this.freeze();
if (this.connector.discoverPrimaryKeys) { if (this.connector.discoverPrimaryKeys) {
this.connector.discoverPrimaryKeys(modelName, options, cb); this.connector.discoverPrimaryKeys(modelName, options, cb);
@ -780,7 +772,7 @@ DataSource.prototype.discoverPrimaryKeys= function(modelName, options, cb) {
* @param {Object} options The options * @param {Object} options The options
* @returns {*} * @returns {*}
*/ */
DataSource.prototype.discoverPrimaryKeysSync= function(modelName, options) { DataSource.prototype.discoverPrimaryKeysSync = function (modelName, options) {
this.freeze(); this.freeze();
if (this.connector.discoverPrimaryKeysSync) { if (this.connector.discoverPrimaryKeysSync) {
return this.connector.discoverPrimaryKeysSync(modelName, options); return this.connector.discoverPrimaryKeysSync(modelName, options);
@ -812,7 +804,7 @@ DataSource.prototype.discoverPrimaryKeysSync= function(modelName, options) {
* @param {Function} [cb] The callback function * @param {Function} [cb] The callback function
* *
*/ */
DataSource.prototype.discoverForeignKeys= function(modelName, options, cb) { DataSource.prototype.discoverForeignKeys = function (modelName, options, cb) {
this.freeze(); this.freeze();
if (this.connector.discoverForeignKeys) { if (this.connector.discoverForeignKeys) {
this.connector.discoverForeignKeys(modelName, options, cb); this.connector.discoverForeignKeys(modelName, options, cb);
@ -828,7 +820,7 @@ DataSource.prototype.discoverForeignKeys= function(modelName, options, cb) {
* @param {Object} options The options * @param {Object} options The options
* @returns {*} * @returns {*}
*/ */
DataSource.prototype.discoverForeignKeysSync= function(modelName, options) { DataSource.prototype.discoverForeignKeysSync = function (modelName, options) {
this.freeze(); this.freeze();
if (this.connector.discoverForeignKeysSync) { if (this.connector.discoverForeignKeysSync) {
return this.connector.discoverForeignKeysSync(modelName, options); return this.connector.discoverForeignKeysSync(modelName, options);
@ -860,7 +852,7 @@ DataSource.prototype.discoverForeignKeysSync= function(modelName, options) {
* @param {Object} options The options * @param {Object} options The options
* @param {Function} [cb] The callback function * @param {Function} [cb] The callback function
*/ */
DataSource.prototype.discoverExportedForeignKeys= function(modelName, options, cb) { DataSource.prototype.discoverExportedForeignKeys = function (modelName, options, cb) {
this.freeze(); this.freeze();
if (this.connector.discoverExportedForeignKeys) { if (this.connector.discoverExportedForeignKeys) {
this.connector.discoverExportedForeignKeys(modelName, options, cb); this.connector.discoverExportedForeignKeys(modelName, options, cb);
@ -875,13 +867,13 @@ DataSource.prototype.discoverExportedForeignKeys= function(modelName, options, c
* @param {Object} options The options * @param {Object} options The options
* @returns {*} * @returns {*}
*/ */
DataSource.prototype.discoverExportedForeignKeysSync= function(modelName, options) { DataSource.prototype.discoverExportedForeignKeysSync = function (modelName, options) {
this.freeze(); this.freeze();
if (this.connector.discoverExportedForeignKeysSync) { if (this.connector.discoverExportedForeignKeysSync) {
return this.connector.discoverExportedForeignKeysSync(modelName, options); return this.connector.discoverExportedForeignKeysSync(modelName, options);
} }
return null; return null;
} };
function capitalize(str) { function capitalize(str) {
if (!str) { if (!str) {
@ -913,19 +905,19 @@ function fromDBName(dbName, camelCase) {
DataSource.prototype.discoverSchema = function (modelName, options, cb) { DataSource.prototype.discoverSchema = function (modelName, options, cb) {
options = options || {}; options = options || {};
if(!cb && 'function' === typeof options) { if (!cb && 'function' === typeof options) {
cb = options; cb = options;
options = {}; options = {};
} }
options.visited = {}; options.visited = {};
options.relations = false; options.relations = false;
this.discoverSchemas(modelName, options, function(err, schemas) { this.discoverSchemas(modelName, options, function (err, schemas) {
if(err) { if (err) {
cb && cb(err, schemas); cb && cb(err, schemas);
return; return;
} }
for(var s in schemas) { for (var s in schemas) {
cb && cb(null, schemas[s]); cb && cb(null, schemas[s]);
return; return;
} }
@ -949,7 +941,7 @@ DataSource.prototype.discoverSchema = function (modelName, options, cb) {
DataSource.prototype.discoverSchemas = function (modelName, options, cb) { DataSource.prototype.discoverSchemas = function (modelName, options, cb) {
options = options || {}; options = options || {};
if(!cb && 'function' === typeof options) { if (!cb && 'function' === typeof options) {
cb = options; cb = options;
options = {}; options = {};
} }
@ -1033,7 +1025,7 @@ DataSource.prototype.discoverSchemas = function (modelName, options, cb) {
options.visited = options.visited || {}; options.visited = options.visited || {};
var schemaKey = columns[0].owner + '.' + modelName; var schemaKey = columns[0].owner + '.' + modelName;
if (!options.visited.hasOwnProperty(schemaKey)) { if (!options.visited.hasOwnProperty(schemaKey)) {
if(self.settings.debug) { if (self.settings.debug) {
console.log('Adding schema for ' + schemaKey); console.log('Adding schema for ' + schemaKey);
} }
options.visited[schemaKey] = schema; options.visited[schemaKey] = schema;
@ -1083,11 +1075,11 @@ DataSource.prototype.discoverSchemas = function (modelName, options, cb) {
} else { } else {
var moreTasks = []; var moreTasks = [];
for (var t in otherTables) { for (var t in otherTables) {
if(self.settings.debug) { if (self.settings.debug) {
console.log('Discovering related schema for ' + schemaKey); console.log('Discovering related schema for ' + schemaKey);
} }
var newOptions = {}; var newOptions = {};
for(var key in options) { for (var key in options) {
newOptions[key] = options[key]; newOptions[key] = options[key];
} }
newOptions.owner = otherTables[t].owner; newOptions.owner = otherTables[t].owner;
@ -1102,7 +1094,6 @@ DataSource.prototype.discoverSchemas = function (modelName, options, cb) {
}); });
}; };
/** /**
* Discover schema from a given table/view synchronously * Discover schema from a given table/view synchronously
* *
@ -1234,7 +1225,7 @@ DataSource.prototype.discoverSchemasSync = function (modelName, options) {
console.log('Discovering related schema for ' + schemaKey); console.log('Discovering related schema for ' + schemaKey);
} }
var newOptions = {}; var newOptions = {};
for(var key in options) { for (var key in options) {
newOptions[key] = options[key]; newOptions[key] = options[key];
} }
newOptions.owner = otherTables[t].owner; newOptions.owner = otherTables[t].owner;
@ -1275,7 +1266,7 @@ DataSource.prototype.discoverAndBuildModels = function (modelName, options, cb)
var models = self.modelBuilder.buildModels(schemaList); var models = self.modelBuilder.buildModels(schemaList);
// Now attach the models to the data source // Now attach the models to the data source
for(var m in models) { for (var m in models) {
models[m].attachTo(self); models[m].attachTo(self);
} }
cb && cb(err, models); cb && cb(err, models);
@ -1323,7 +1314,7 @@ DataSource.prototype.isActual = function (models, cb) {
models = undefined; models = undefined;
} }
if (cb) { if (cb) {
process.nextTick(function() { process.nextTick(function () {
cb(null, true); cb(null, true);
}); });
} }
@ -1394,7 +1385,7 @@ DataSource.prototype.columnNames = function (modelName) {
* @param {String} modelName The model name * @param {String} modelName The model name
* @returns {String} columnName for ID * @returns {String} columnName for ID
*/ */
DataSource.prototype.idColumnName = function(modelName) { DataSource.prototype.idColumnName = function (modelName) {
return this.getModelDefinition(modelName).idColumnName(this.connector.name); return this.getModelDefinition(modelName).idColumnName(this.connector.name);
}; };
@ -1403,8 +1394,8 @@ DataSource.prototype.idColumnName = function(modelName) {
* @param {String} modelName The model name * @param {String} modelName The model name
* @returns {String} property name for ID * @returns {String} property name for ID
*/ */
DataSource.prototype.idName = function(modelName) { DataSource.prototype.idName = function (modelName) {
if(!this.getModelDefinition(modelName).idName) { if (!this.getModelDefinition(modelName).idName) {
console.error('No id name', this.getModelDefinition(modelName)); console.error('No id name', this.getModelDefinition(modelName));
} }
return this.getModelDefinition(modelName).idName(); return this.getModelDefinition(modelName).idName();
@ -1419,7 +1410,6 @@ DataSource.prototype.idNames = function (modelName) {
return this.getModelDefinition(modelName).idNames(); return this.getModelDefinition(modelName).idNames();
}; };
/** /**
* Define foreign key to another model * Define foreign key to another model
* @param {String} className The model name that owns the key * @param {String} className The model name that owns the key
@ -1431,10 +1421,10 @@ DataSource.prototype.defineForeignKey = function defineForeignKey(className, key
if (this.getModelDefinition(className).rawProperties[key]) return; if (this.getModelDefinition(className).rawProperties[key]) return;
var defaultType = Number; var defaultType = Number;
if(foreignClassName) { if (foreignClassName) {
var foreignModel = this.getModelDefinition(foreignClassName); var foreignModel = this.getModelDefinition(foreignClassName);
var pkName = foreignModel && foreignModel.idName(); var pkName = foreignModel && foreignModel.idName();
if(pkName) { if (pkName) {
defaultType = foreignModel.properties[pkName].type; defaultType = foreignModel.properties[pkName].type;
} }
} }
@ -1467,12 +1457,12 @@ DataSource.prototype.defineForeignKey = function defineForeignKey(className, key
DataSource.prototype.disconnect = function disconnect(cb) { DataSource.prototype.disconnect = function disconnect(cb) {
var self = this; var self = this;
if (this.connected && (typeof this.connector.disconnect === 'function')) { if (this.connected && (typeof this.connector.disconnect === 'function')) {
this.connector.disconnect(function(err, result) { this.connector.disconnect(function (err, result) {
self.connected = false; self.connected = false;
cb && cb(err, result); cb && cb(err, result);
}); });
} else { } else {
process.nextTick(function() { process.nextTick(function () {
cb && cb(); cb && cb();
}); });
} }
@ -1526,7 +1516,7 @@ DataSource.prototype.copyModel = function copyModel(Master) {
* @returns {EventEmitter} * @returns {EventEmitter}
* @private * @private
*/ */
DataSource.prototype.transaction = function() { DataSource.prototype.transaction = function () {
var dataSource = this; var dataSource = this;
var transaction = new EventEmitter(); var transaction = new EventEmitter();
@ -1551,7 +1541,7 @@ DataSource.prototype.transaction = function() {
dataSource.copyModel.call(transaction, dataSource.modelBuilder.models[i]); dataSource.copyModel.call(transaction, dataSource.modelBuilder.models[i]);
} }
transaction.exec = function(cb) { transaction.exec = function (cb) {
transaction.connector.exec(cb); transaction.connector.exec(cb);
}; };
@ -1565,7 +1555,7 @@ DataSource.prototype.transaction = function() {
DataSource.prototype.enableRemote = function (operation) { DataSource.prototype.enableRemote = function (operation) {
var op = this.getOperation(operation); var op = this.getOperation(operation);
if(op) { if (op) {
op.remoteEnabled = true; op.remoteEnabled = true;
} else { } else {
throw new Error(operation + ' is not provided by the attached connector'); throw new Error(operation + ' is not provided by the attached connector');
@ -1579,7 +1569,7 @@ DataSource.prototype.enableRemote = function (operation) {
DataSource.prototype.disableRemote = function (operation) { DataSource.prototype.disableRemote = function (operation) {
var op = this.getOperation(operation); var op = this.getOperation(operation);
if(op) { if (op) {
op.remoteEnabled = false; op.remoteEnabled = false;
} else { } else {
throw new Error(operation + ' is not provided by the attached connector'); throw new Error(operation + ' is not provided by the attached connector');
@ -1595,10 +1585,10 @@ DataSource.prototype.getOperation = function (operation) {
var ops = this.operations(); var ops = this.operations();
var opKeys = Object.keys(ops); var opKeys = Object.keys(ops);
for(var i = 0; i < opKeys.length; i++) { for (var i = 0; i < opKeys.length; i++) {
var op = ops[opKeys[i]]; var op = ops[opKeys[i]];
if(op.name === operation) { if (op.name === operation) {
return op; return op;
} }
} }
@ -1627,7 +1617,7 @@ DataSource.prototype.defineOperation = function (name, options, fn) {
* Check if the backend is a relational DB * Check if the backend is a relational DB
* @returns {Boolean} * @returns {Boolean}
*/ */
DataSource.prototype.isRelational = function() { DataSource.prototype.isRelational = function () {
return this.connector && this.connector.relational; return this.connector && this.connector.relational;
}; };
@ -1637,7 +1627,7 @@ DataSource.prototype.isRelational = function() {
* @param args * @param args
* @returns {boolean} * @returns {boolean}
*/ */
DataSource.prototype.ready = function(obj, args) { DataSource.prototype.ready = function (obj, args) {
var self = this; var self = this;
if (this.connected) { if (this.connected) {
// Connected // Connected
@ -1658,7 +1648,7 @@ DataSource.prototype.ready = function(obj, args) {
self.removeListener('connected', onConnected); self.removeListener('connected', onConnected);
var params = [].slice.call(args); var params = [].slice.call(args);
var cb = params.pop(); var cb = params.pop();
if(typeof cb === 'function') { if (typeof cb === 'function') {
cb(err); cb(err);
} }
}; };
@ -1670,7 +1660,6 @@ DataSource.prototype.ready = function(obj, args) {
return true; return true;
}; };
/** /**
* Define a hidden property * Define a hidden property
* @param {Object} obj The property owner * @param {Object} obj The property owner
@ -1702,7 +1691,6 @@ function defineReadonlyProp(obj, key, value) {
}); });
} }
// Carry over a few properties/methods from the ModelBuilder as some tests use them // Carry over a few properties/methods from the ModelBuilder as some tests use them
DataSource.Text = ModelBuilder.Text; DataSource.Text = ModelBuilder.Text;
DataSource.JSON = ModelBuilder.JSON; DataSource.JSON = ModelBuilder.JSON;
@ -1712,7 +1700,7 @@ DataSource.Any = ModelBuilder.Any;
* @deprecated Use ModelBuilder.registerType instead * @deprecated Use ModelBuilder.registerType instead
* @param type * @param type
*/ */
DataSource.registerType = function(type) { DataSource.registerType = function (type) {
ModelBuilder.registerType(type); ModelBuilder.registerType(type);
}; };

View File

@ -11,11 +11,11 @@ var assert = require('assert');
exports.nearFilter = function nearFilter(where) { exports.nearFilter = function nearFilter(where) {
var result = false; var result = false;
if(where && typeof where === 'object') { if (where && typeof where === 'object') {
Object.keys(where).forEach(function (key) { Object.keys(where).forEach(function (key) {
var ex = where[key]; var ex = where[key];
if(ex && ex.near) { if (ex && ex.near) {
result = { result = {
near: ex.near, near: ex.near,
maxDistance: ex.maxDistance, maxDistance: ex.maxDistance,
@ -45,18 +45,18 @@ exports.filter = function (arr, filter) {
var loc = obj[key]; var loc = obj[key];
// filter out objects without locations // filter out objects without locations
if(!loc) return; if (!loc) return;
if(!(loc instanceof GeoPoint)) { if (!(loc instanceof GeoPoint)) {
loc = GeoPoint(loc); loc = GeoPoint(loc);
} }
if(typeof loc.lat !== 'number') return; if (typeof loc.lat !== 'number') return;
if(typeof loc.lng !== 'number') return; if (typeof loc.lng !== 'number') return;
var d = GeoPoint.distanceBetween(origin, loc); var d = GeoPoint.distanceBetween(origin, loc);
if(max && d > max) { if (max && d > max) {
// dont add // dont add
} else { } else {
distances[obj.id] = d; distances[obj.id] = d;
@ -68,11 +68,11 @@ exports.filter = function (arr, filter) {
var a = objB[key]; var a = objB[key];
var b = objB[key]; var b = objB[key];
if(a && b) { if (a && b) {
var da = distances[objA.id]; var da = distances[objA.id];
var db = distances[objB.id]; var db = distances[objB.id];
if(db === da) return 0; if (db === da) return 0;
return da > db ? 1 : -1; return da > db ? 1 : -1;
} else { } else {
return 0; return 0;
@ -87,15 +87,15 @@ exports.filter = function (arr, filter) {
exports.GeoPoint = GeoPoint; exports.GeoPoint = GeoPoint;
function GeoPoint(data) { function GeoPoint(data) {
if(!(this instanceof GeoPoint)) { if (!(this instanceof GeoPoint)) {
return new GeoPoint(data); return new GeoPoint(data);
} }
if(typeof data === 'string') { if (typeof data === 'string') {
data = data.split(/,\s*/); data = data.split(/,\s*/);
assert(data.length === 2, 'must provide a string "lng,lat" creating a GeoPoint with a string'); assert(data.length === 2, 'must provide a string "lng,lat" creating a GeoPoint with a string');
} }
if(Array.isArray(data)) { if (Array.isArray(data)) {
data = { data = {
lng: Number(data[0]), lng: Number(data[0]),
lat: Number(data[1]) lat: Number(data[1])
@ -122,10 +122,10 @@ function GeoPoint(data) {
*/ */
GeoPoint.distanceBetween = function distanceBetween(a, b, options) { GeoPoint.distanceBetween = function distanceBetween(a, b, options) {
if(!(a instanceof GeoPoint)) { if (!(a instanceof GeoPoint)) {
a = GeoPoint(a); a = GeoPoint(a);
} }
if(!(b instanceof GeoPoint)) { if (!(b instanceof GeoPoint)) {
b = GeoPoint(b); b = GeoPoint(b);
} }
@ -184,12 +184,12 @@ function geoDistance(x1, y1, x2, y2, options) {
x2 = x2 * DEG2RAD; x2 = x2 * DEG2RAD;
y2 = y2 * DEG2RAD; y2 = y2 * DEG2RAD;
var a = Math.pow(Math.sin(( y2-y1 ) / 2.0 ), 2); var a = Math.pow(Math.sin(( y2 - y1 ) / 2.0), 2);
var b = Math.pow(Math.sin(( x2-x1 ) / 2.0 ), 2); var b = Math.pow(Math.sin(( x2 - x1 ) / 2.0), 2);
var c = Math.sqrt( a + Math.cos( y2 ) * Math.cos( y1 ) * b ); var c = Math.sqrt(a + Math.cos(y2) * Math.cos(y1) * b);
var type = (options && options.type) || 'miles'; var type = (options && options.type) || 'miles';
return 2 * Math.asin( c ) * EARTH_RADIUS[type]; return 2 * Math.asin(c) * EARTH_RADIUS[type];
} }

View File

@ -28,8 +28,10 @@ Hookable.afterDestroy = null;
// TODO: Evaluate https://github.com/bnoguchi/hooks-js/ // TODO: Evaluate https://github.com/bnoguchi/hooks-js/
Hookable.prototype.trigger = function trigger(actionName, work, data) { Hookable.prototype.trigger = function trigger(actionName, work, data) {
var capitalizedName = capitalize(actionName); var capitalizedName = capitalize(actionName);
var beforeHook = this.constructor["before" + capitalizedName] || this.constructor["pre" + capitalizedName]; var beforeHook = this.constructor["before" + capitalizedName]
var afterHook = this.constructor["after" + capitalizedName] || this.constructor["post" + capitalizedName]; || this.constructor["pre" + capitalizedName];
var afterHook = this.constructor["after" + capitalizedName]
|| this.constructor["post" + capitalizedName];
if (actionName === 'validate') { if (actionName === 'validate') {
beforeHook = beforeHook || this.constructor.beforeValidation; beforeHook = beforeHook || this.constructor.beforeValidation;
afterHook = afterHook || this.constructor.afterValidation; afterHook = afterHook || this.constructor.afterValidation;

View File

@ -46,7 +46,7 @@ Inclusion.include = function (objects, include, cb) {
var callback = processIncludeItem(objects, include[i], keyVals, objsByKeys); var callback = processIncludeItem(objects, include[i], keyVals, objsByKeys);
if (callback !== null) { if (callback !== null) {
nbCallbacks++; nbCallbacks++;
callback(function() { callback(function () {
nbCallbacks--; nbCallbacks--;
if (nbCallbacks == 0) { if (nbCallbacks == 0) {
cb(null, objects); cb(null, objects);
@ -86,8 +86,9 @@ Inclusion.include = function (objects, include, cb) {
var relation = relations[relationName]; var relation = relations[relationName];
if (!relation) { if (!relation) {
return function() { return function () {
cb(new Error('Relation "' + relationName + '" is not defined for ' + self.modelName + ' model')); cb(new Error('Relation "' + relationName + '" is not defined for '
+ self.modelName + ' model'));
} }
} }
@ -95,7 +96,7 @@ Inclusion.include = function (objects, include, cb) {
if (!keyVals[relation.keyFrom]) { if (!keyVals[relation.keyFrom]) {
objsByKeys[relation.keyFrom] = {}; objsByKeys[relation.keyFrom] = {};
objs.filter(Boolean).forEach(function(obj) { objs.filter(Boolean).forEach(function (obj) {
if (!objsByKeys[relation.keyFrom][obj[relation.keyFrom]]) { if (!objsByKeys[relation.keyFrom][obj[relation.keyFrom]]) {
objsByKeys[relation.keyFrom][obj[relation.keyFrom]] = []; objsByKeys[relation.keyFrom][obj[relation.keyFrom]] = [];
} }
@ -110,7 +111,8 @@ Inclusion.include = function (objects, include, cb) {
var inValues = []; var inValues = [];
for (var j = 0; j < keyVals[relation.keyFrom].length; j++) { for (var j = 0; j < keyVals[relation.keyFrom].length; j++) {
keysToBeProcessed[keyVals[relation.keyFrom][j]] = true; keysToBeProcessed[keyVals[relation.keyFrom][j]] = true;
if (keyVals[relation.keyFrom][j] !== 'null' && keyVals[relation.keyFrom][j] !== 'undefined') { if (keyVals[relation.keyFrom][j] !== 'null'
&& keyVals[relation.keyFrom][j] !== 'undefined') {
inValues.push(keyVals[relation.keyFrom][j]); inValues.push(keyVals[relation.keyFrom][j]);
} }
} }
@ -118,8 +120,8 @@ Inclusion.include = function (objects, include, cb) {
req['where'][relation.keyTo] = {inq: inValues}; req['where'][relation.keyTo] = {inq: inValues};
req['include'] = subInclude; req['include'] = subInclude;
return function(cb) { return function (cb) {
relation.modelTo.find(req, function(err, objsIncluded) { relation.modelTo.find(req, function (err, objsIncluded) {
for (var i = 0; i < objsIncluded.length; i++) { for (var i = 0; i < objsIncluded.length; i++) {
delete keysToBeProcessed[objsIncluded[i][relation.keyTo]]; delete keysToBeProcessed[objsIncluded[i][relation.keyTo]];
var objectsFrom = objsByKeys[relation.keyFrom][objsIncluded[i][relation.keyTo]]; var objectsFrom = objsByKeys[relation.keyFrom][objsIncluded[i][relation.keyTo]];
@ -145,7 +147,8 @@ Inclusion.include = function (objects, include, cb) {
if (!objectsFrom[j].__cachedRelations) { if (!objectsFrom[j].__cachedRelations) {
objectsFrom[j].__cachedRelations = {}; objectsFrom[j].__cachedRelations = {};
} }
objectsFrom[j].__cachedRelations[relationName] = relation.multiple ? [] : null; objectsFrom[j].__cachedRelations[relationName] =
relation.multiple ? [] : null;
} }
} }
cb(err, objsIncluded); cb(err, objsIncluded);
@ -153,7 +156,6 @@ Inclusion.include = function (objects, include, cb) {
}; };
} }
return null; return null;
} }
} }

View File

@ -14,7 +14,8 @@ exports.inherits = function (newClass, baseClass, options) {
if (options.staticProperties) { if (options.staticProperties) {
Object.keys(baseClass).forEach(function (classProp) { Object.keys(baseClass).forEach(function (classProp) {
if (classProp !== 'super_' && (!newClass.hasOwnProperty(classProp) || options.override)) { if (classProp !== 'super_' && (!newClass.hasOwnProperty(classProp)
|| options.override)) {
var pd = Object.getOwnPropertyDescriptor(baseClass, classProp); var pd = Object.getOwnPropertyDescriptor(baseClass, classProp);
Object.defineProperty(newClass, classProp, pd); Object.defineProperty(newClass, classProp, pd);
} }
@ -22,7 +23,6 @@ exports.inherits = function (newClass, baseClass, options) {
} }
}; };
/** /**
* Mix in the a class into the new class * Mix in the a class into the new class
* @param newClass The target class to receive the mixin * @param newClass The target class to receive the mixin
@ -31,7 +31,7 @@ exports.inherits = function (newClass, baseClass, options) {
*/ */
exports.mixin = function (newClass, mixinClass, options) { exports.mixin = function (newClass, mixinClass, options) {
if (Array.isArray(newClass._mixins)) { if (Array.isArray(newClass._mixins)) {
if(newClass._mixins.indexOf(mixinClass) !== -1) { if (newClass._mixins.indexOf(mixinClass) !== -1) {
return; return;
} }
newClass._mixins.push(mixinClass); newClass._mixins.push(mixinClass);
@ -46,20 +46,22 @@ exports.mixin = function (newClass, mixinClass, options) {
proxyFunctions: false proxyFunctions: false
}; };
if(options.staticProperties === undefined) { if (options.staticProperties === undefined) {
options.staticProperties = true; options.staticProperties = true;
} }
if(options.instanceProperties === undefined) { if (options.instanceProperties === undefined) {
options.instanceProperties = true; options.instanceProperties = true;
} }
if (options.staticProperties) { if (options.staticProperties) {
var staticProxies = []; var staticProxies = [];
Object.keys(mixinClass).forEach(function (classProp) { Object.keys(mixinClass).forEach(function (classProp) {
if (classProp !== 'super_' && classProp !== '_mixins' && (!newClass.hasOwnProperty(classProp) || options.override)) { if (classProp !== 'super_' && classProp !== '_mixins'
&& (!newClass.hasOwnProperty(classProp) || options.override)) {
var pd = Object.getOwnPropertyDescriptor(mixinClass, classProp); var pd = Object.getOwnPropertyDescriptor(mixinClass, classProp);
if(options.proxyFunctions && pd.writable && typeof pd.value === 'function') { if (options.proxyFunctions && pd.writable
&& typeof pd.value === 'function') {
pd.value = exports.proxy(pd.value, staticProxies); pd.value = exports.proxy(pd.value, staticProxies);
} }
Object.defineProperty(newClass, classProp, pd); Object.defineProperty(newClass, classProp, pd);
@ -73,7 +75,7 @@ exports.mixin = function (newClass, mixinClass, options) {
Object.keys(mixinClass.prototype).forEach(function (instanceProp) { Object.keys(mixinClass.prototype).forEach(function (instanceProp) {
if (!newClass.prototype.hasOwnProperty(instanceProp) || options.override) { if (!newClass.prototype.hasOwnProperty(instanceProp) || options.override) {
var pd = Object.getOwnPropertyDescriptor(mixinClass.prototype, instanceProp); var pd = Object.getOwnPropertyDescriptor(mixinClass.prototype, instanceProp);
if(options.proxyFunctions && pd.writable && typeof pd.value === 'function') { if (options.proxyFunctions && pd.writable && typeof pd.value === 'function') {
pd.value = exports.proxy(pd.value, instanceProxies); pd.value = exports.proxy(pd.value, instanceProxies);
} }
Object.defineProperty(newClass.prototype, instanceProp, pd); Object.defineProperty(newClass.prototype, instanceProp, pd);
@ -85,21 +87,21 @@ exports.mixin = function (newClass, mixinClass, options) {
return newClass; return newClass;
}; };
exports.proxy = function(fn, proxies) { exports.proxy = function (fn, proxies) {
// Make sure same methods referenced by different properties have the same proxy // Make sure same methods referenced by different properties have the same proxy
// For example, deleteById is an alias of removeById // For example, deleteById is an alias of removeById
proxies = proxies || []; proxies = proxies || [];
for(var i = 0; i<proxies.length; i++) { for (var i = 0; i < proxies.length; i++) {
if(proxies[i]._delegate === fn) { if (proxies[i]._delegate === fn) {
return proxies[i]; return proxies[i];
} }
} }
var f = function() { var f = function () {
return fn.apply(this, arguments); return fn.apply(this, arguments);
}; };
f._delegate = fn; f._delegate = fn;
proxies.push(f); proxies.push(f);
Object.keys(fn).forEach(function(x) { Object.keys(fn).forEach(function (x) {
f[x] = fn[x]; f[x] = fn[x];
}); });
return f; return f;

View File

@ -1,4 +1,3 @@
module.exports = List; module.exports = List;
/** /**
@ -15,10 +14,10 @@ function List(data, type, parent) {
return new List(data, type, parent); return new List(data, type, parent);
} }
if(typeof data === 'string') { if (typeof data === 'string') {
try { try {
data = JSON.parse(data); data = JSON.parse(data);
} catch(e) { } catch (e) {
throw new Error('could not create List from JSON string: ', data); throw new Error('could not create List from JSON string: ', data);
} }
} }
@ -45,7 +44,7 @@ function List(data, type, parent) {
Item = list.ItemType = type[0] || ListItem; Item = list.ItemType = type[0] || ListItem;
} }
data.forEach(function(item, i) { data.forEach(function (item, i) {
data[i] = Item(item, list); data[i] = Item(item, list);
Object.defineProperty(list, data[i].id, { Object.defineProperty(list, data[i].id, {
writable: true, writable: true,
@ -61,7 +60,7 @@ function List(data, type, parent) {
Object.defineProperty(list, 'length', { Object.defineProperty(list, 'length', {
enumerable: false, enumerable: false,
configurable: true, configurable: true,
get: function() { get: function () {
return list.items.length; return list.items.length;
} }
}); });
@ -119,8 +118,8 @@ if (_) {
'range' 'range'
]; ];
_import.forEach(function(name) { _import.forEach(function (name) {
List.prototype[name] = function() { List.prototype[name] = function () {
var args = [].slice.call(arguments); var args = [].slice.call(arguments);
args.unshift(this.items); args.unshift(this.items);
return _[name].apply(_, args); return _[name].apply(_, args);
@ -135,10 +134,10 @@ if (_) {
}; };
}); });
List.prototype.find = function(pattern, field) { List.prototype.find = function (pattern, field) {
if (field) { if (field) {
var res; var res;
this.items.forEach(function(o) { this.items.forEach(function (o) {
if (o[field] == pattern) res = o; if (o[field] == pattern) res = o;
}); });
return res; return res;
@ -147,10 +146,10 @@ List.prototype.find = function(pattern, field) {
} }
}; };
List.prototype.toObject = function(onlySchema) { List.prototype.toObject = function (onlySchema) {
var items = []; var items = [];
this.items.forEach(function(item) { this.items.forEach(function (item) {
if(item.toObject) { if (item.toObject) {
items.push(item.toObject(onlySchema)); items.push(item.toObject(onlySchema));
} else { } else {
items.push(item); items.push(item);
@ -159,28 +158,28 @@ List.prototype.toObject = function(onlySchema) {
return items; return items;
}; };
List.prototype.toJSON = function() { List.prototype.toJSON = function () {
return this.toObject(true); return this.toObject(true);
}; };
List.prototype.toString = function() { List.prototype.toString = function () {
return JSON.stringify(this.items); return JSON.stringify(this.items);
}; };
List.prototype.autoincrement = function() { List.prototype.autoincrement = function () {
return this.nextid++; return this.nextid++;
}; };
List.prototype.push = function(obj) { List.prototype.push = function (obj) {
var item = new ListItem(obj, this); var item = new ListItem(obj, this);
this.items.push(item); this.items.push(item);
return item; return item;
}; };
List.prototype.remove = function(obj) { List.prototype.remove = function (obj) {
var id = obj.id ? obj.id : obj; var id = obj.id ? obj.id : obj;
var found = false; var found = false;
this.items.forEach(function(o, i) { this.items.forEach(function (o, i) {
if (id && o.id == id) { if (id && o.id == id) {
found = i; found = i;
if (o.id !== id) { if (o.id !== id) {
@ -194,20 +193,20 @@ List.prototype.remove = function(obj) {
} }
}; };
List.prototype.sort = function(cb) { List.prototype.sort = function (cb) {
return this.items.sort(cb); return this.items.sort(cb);
}; };
List.prototype.map = function(cb) { List.prototype.map = function (cb) {
if (typeof cb === 'function') return this.items.map(cb); if (typeof cb === 'function') return this.items.map(cb);
if (typeof cb === 'string') return this.items.map(function(el) { if (typeof cb === 'string') return this.items.map(function (el) {
if (typeof el[cb] === 'function') return el[cb](); if (typeof el[cb] === 'function') return el[cb]();
if (el.hasOwnProperty(cb)) return el[cb]; if (el.hasOwnProperty(cb)) return el[cb];
}); });
}; };
function ListItem(data, parent) { function ListItem(data, parent) {
if(!(this instanceof ListItem)) { if (!(this instanceof ListItem)) {
return new ListItem(data, parent); return new ListItem(data, parent);
} }
if (typeof data === 'object') { if (typeof data === 'object') {
@ -231,7 +230,7 @@ function ListItem(data, parent) {
} }
} }
this.save = function(c) { this.save = function (c) {
parent.parent.save(c); parent.parent.save(c);
}; };
} }

View File

@ -50,7 +50,7 @@ util.inherits(ModelBuilder, EventEmitter);
ModelBuilder.defaultInstance = new ModelBuilder(); ModelBuilder.defaultInstance = new ModelBuilder();
function isModelClass(cls) { function isModelClass(cls) {
if(!cls) { if (!cls) {
return false; return false;
} }
return cls.prototype instanceof DefaultModelBaseClass; return cls.prototype instanceof DefaultModelBaseClass;
@ -63,15 +63,15 @@ function isModelClass(cls) {
* given name if a model doesn't exist * given name if a model doesn't exist
* @returns {*} The model class * @returns {*} The model class
*/ */
ModelBuilder.prototype.getModel = function(name, forceCreate) { ModelBuilder.prototype.getModel = function (name, forceCreate) {
var model = this.models[name]; var model = this.models[name];
if(!model && forceCreate) { if (!model && forceCreate) {
model = this.define(name, {}, {unresolved: true}); model = this.define(name, {}, {unresolved: true});
} }
return model; return model;
}; };
ModelBuilder.prototype.getModelDefinition = function(name) { ModelBuilder.prototype.getModelDefinition = function (name) {
return this.definitions[name]; return this.definitions[name];
}; };
@ -128,15 +128,15 @@ ModelBuilder.prototype.define = function defineClass(className, properties, sett
settings = settings || {}; settings = settings || {};
// Set the strict mode to be false by default // Set the strict mode to be false by default
if(settings.strict === undefined || settings.strict === null) { if (settings.strict === undefined || settings.strict === null) {
settings.strict = false; settings.strict = false;
} }
// Set up the base model class // Set up the base model class
var ModelBaseClass = parent || DefaultModelBaseClass; var ModelBaseClass = parent || DefaultModelBaseClass;
var baseClass = settings.base || settings['super']; var baseClass = settings.base || settings['super'];
if(baseClass) { if (baseClass) {
if(isModelClass(baseClass)) { if (isModelClass(baseClass)) {
ModelBaseClass = baseClass; ModelBaseClass = baseClass;
} else { } else {
ModelBaseClass = this.models[baseClass]; ModelBaseClass = this.models[baseClass];
@ -149,17 +149,17 @@ ModelBuilder.prototype.define = function defineClass(className, properties, sett
// Create the ModelClass if it doesn't exist or it's resolved (override) // Create the ModelClass if it doesn't exist or it's resolved (override)
// TODO: [rfeng] We need to decide what names to use for built-in models such as User. // TODO: [rfeng] We need to decide what names to use for built-in models such as User.
if(!ModelClass || !ModelClass.settings.unresolved) { if (!ModelClass || !ModelClass.settings.unresolved) {
// every class can receive hash of data as optional param // every class can receive hash of data as optional param
ModelClass = function ModelConstructor(data, dataSource) { ModelClass = function ModelConstructor(data, dataSource) {
if(!(this instanceof ModelConstructor)) { if (!(this instanceof ModelConstructor)) {
return new ModelConstructor(data, dataSource); return new ModelConstructor(data, dataSource);
} }
if(ModelClass.settings.unresolved) { if (ModelClass.settings.unresolved) {
throw new Error('Model ' + ModelClass.modelName + ' is not defined.'); throw new Error('Model ' + ModelClass.modelName + ' is not defined.');
} }
ModelBaseClass.apply(this, arguments); ModelBaseClass.apply(this, arguments);
if(dataSource) { if (dataSource) {
hiddenProperty(this, '__dataSource', dataSource); hiddenProperty(this, '__dataSource', dataSource);
} }
}; };
@ -179,7 +179,7 @@ ModelBuilder.prototype.define = function defineClass(className, properties, sett
this.models[className] = ModelClass; this.models[className] = ModelClass;
// Return the unresolved model // Return the unresolved model
if(settings.unresolved) { if (settings.unresolved) {
ModelClass.settings = {unresolved: true}; ModelClass.settings = {unresolved: true};
return ModelClass; return ModelClass;
} }
@ -194,14 +194,14 @@ ModelBuilder.prototype.define = function defineClass(className, properties, sett
// inherit ModelBaseClass static methods // inherit ModelBaseClass static methods
for (var i in ModelBaseClass) { for (var i in ModelBaseClass) {
// We need to skip properties that are already in the subclass, for example, the event emitter methods // We need to skip properties that are already in the subclass, for example, the event emitter methods
if(i !== '_mixins' && !(i in ModelClass)) { if (i !== '_mixins' && !(i in ModelClass)) {
ModelClass[i] = ModelBaseClass[i]; ModelClass[i] = ModelBaseClass[i];
} }
} }
// Load and inject the model classes // Load and inject the model classes
if(settings.models) { if (settings.models) {
Object.keys(settings.models).forEach(function(m) { Object.keys(settings.models).forEach(function (m) {
var model = settings.models[m]; var model = settings.models[m];
ModelClass[m] = typeof model === 'string' ? modelBuilder.getModel(model, true) : model; ModelClass[m] = typeof model === 'string' ? modelBuilder.getModel(model, true) : model;
}); });
@ -220,13 +220,13 @@ ModelBuilder.prototype.define = function defineClass(className, properties, sett
ModelClass.settings = modelDefinition.settings; ModelClass.settings = modelDefinition.settings;
var idInjection = settings.idInjection; var idInjection = settings.idInjection;
if(idInjection !== false) { if (idInjection !== false) {
// Default to true if undefined // Default to true if undefined
idInjection = true; idInjection = true;
} }
var idNames = modelDefinition.idNames(); var idNames = modelDefinition.idNames();
if(idNames.length > 0) { if (idNames.length > 0) {
// id already exists // id already exists
idInjection = false; idInjection = false;
} }
@ -287,8 +287,8 @@ ModelBuilder.prototype.define = function defineClass(className, properties, sett
// Check if subclass redefines the ids // Check if subclass redefines the ids
var idFound = false; var idFound = false;
for(var k in subclassProperties) { for (var k in subclassProperties) {
if(subclassProperties[k].id) { if (subclassProperties[k].id) {
idFound = true; idFound = true;
break; break;
} }
@ -296,11 +296,11 @@ ModelBuilder.prototype.define = function defineClass(className, properties, sett
// Merging the properties // Merging the properties
Object.keys(properties).forEach(function (key) { Object.keys(properties).forEach(function (key) {
if(idFound && properties[key].id) { if (idFound && properties[key].id) {
// don't inherit id properties // don't inherit id properties
return; return;
} }
if(subclassProperties[key] === undefined) { if (subclassProperties[key] === undefined) {
subclassProperties[key] = properties[key]; subclassProperties[key] = properties[key];
} }
}); });
@ -320,7 +320,7 @@ ModelBuilder.prototype.define = function defineClass(className, properties, sett
var subClass = modelBuilder.define(className, subclassProperties, subclassSettings, ModelClass); var subClass = modelBuilder.define(className, subclassProperties, subclassSettings, ModelClass);
// Calling the setup function // Calling the setup function
if(typeof subClass.setup === 'function') { if (typeof subClass.setup === 'function') {
subClass.setup.call(subClass); subClass.setup.call(subClass);
} }
@ -335,7 +335,7 @@ ModelBuilder.prototype.define = function defineClass(className, properties, sett
var properties = modelDefinition.build(); var properties = modelDefinition.build();
var prop = properties[propertyName]; var prop = properties[propertyName];
var DataType = prop.type; var DataType = prop.type;
if(!DataType) { if (!DataType) {
throw new Error('Invalid type for property ' + propertyName); throw new Error('Invalid type for property ' + propertyName);
} }
if (Array.isArray(DataType) || DataType === Array) { if (Array.isArray(DataType) || DataType === Array) {
@ -345,11 +345,11 @@ ModelBuilder.prototype.define = function defineClass(className, properties, sett
DataType = function Date(arg) { DataType = function Date(arg) {
return new OrigDate(arg); return new OrigDate(arg);
}; };
} else if(typeof DataType === 'string') { } else if (typeof DataType === 'string') {
DataType = modelBuilder.resolveType(DataType); DataType = modelBuilder.resolveType(DataType);
} }
if(prop.required) { if (prop.required) {
var requiredOptions = typeof prop.required === 'object' ? prop.required : undefined; var requiredOptions = typeof prop.required === 'object' ? prop.required : undefined;
ModelClass.validatesPresenceOf(propertyName, requiredOptions); ModelClass.validatesPresenceOf(propertyName, requiredOptions);
} }
@ -372,7 +372,7 @@ ModelBuilder.prototype.define = function defineClass(className, properties, sett
if (value === null || value === undefined) { if (value === null || value === undefined) {
this.__data[propertyName] = value; this.__data[propertyName] = value;
} else { } else {
if(DataType === List) { if (DataType === List) {
this.__data[propertyName] = DataType(value, properties[propertyName].type, this.__data); this.__data[propertyName] = DataType(value, properties[propertyName].type, this.__data);
} else { } else {
// Assume the type constructor handles Constructor() call // Assume the type constructor handles Constructor() call
@ -463,7 +463,6 @@ ModelBuilder.prototype.extendModel = function (model, props) {
}); });
}; };
ModelBuilder.prototype.copyModel = function copyModel(Master) { ModelBuilder.prototype.copyModel = function copyModel(Master) {
var modelBuilder = this; var modelBuilder = this;
var className = Master.modelName; var className = Master.modelName;
@ -493,7 +492,6 @@ ModelBuilder.prototype.copyModel = function copyModel(Master) {
return Slave; return Slave;
}; };
/*! /*!
* Define hidden property * Define hidden property
*/ */
@ -526,7 +524,7 @@ ModelBuilder.prototype.getSchemaName = function (name) {
* @param {String} type The type string, such as 'number', 'Number', 'boolean', or 'String'. It's case insensitive * @param {String} type The type string, such as 'number', 'Number', 'boolean', or 'String'. It's case insensitive
* @returns {Function} if the type is resolved * @returns {Function} if the type is resolved
*/ */
ModelBuilder.prototype.resolveType = function(type) { ModelBuilder.prototype.resolveType = function (type) {
if (!type) { if (!type) {
return type; return type;
} }
@ -557,7 +555,7 @@ ModelBuilder.prototype.resolveType = function(type) {
return this.define(this.getSchemaName(null), return this.define(this.getSchemaName(null),
type, {anonymous: true, idInjection: false}); type, {anonymous: true, idInjection: false});
} }
} else if('function' === typeof type ) { } else if ('function' === typeof type) {
return type; return type;
} }
return type; return type;
@ -610,7 +608,7 @@ ModelBuilder.prototype.buildModels = function (schemas) {
var sourceModel = models[relation.source]; var sourceModel = models[relation.source];
var targetModel = models[relation.target]; var targetModel = models[relation.target];
if (sourceModel && targetModel) { if (sourceModel && targetModel) {
if(typeof sourceModel[relation.type] === 'function') { if (typeof sourceModel[relation.type] === 'function') {
sourceModel[relation.type](targetModel, {as: relation.as}); sourceModel[relation.type](targetModel, {as: relation.as});
} }
} }
@ -625,7 +623,7 @@ ModelBuilder.prototype.buildModels = function (schemas) {
* @param [Object} options The options * @param [Object} options The options
* @returns {} * @returns {}
*/ */
ModelBuilder.prototype.buildModelFromInstance = function(name, json, options) { ModelBuilder.prototype.buildModelFromInstance = function (name, json, options) {
// Introspect the JSON document to generate a schema // Introspect the JSON document to generate a schema
var schema = introspect(json); var schema = introspect(json);

View File

@ -49,14 +49,13 @@ util.inherits(ModelDefinition, EventEmitter);
// Set up types // Set up types
require('./types')(ModelDefinition); require('./types')(ModelDefinition);
/** /**
* Return table name for specified `modelName` * Return table name for specified `modelName`
* @param {String} connectorType The connector type, such as 'oracle' or 'mongodb' * @param {String} connectorType The connector type, such as 'oracle' or 'mongodb'
*/ */
ModelDefinition.prototype.tableName = function (connectorType) { ModelDefinition.prototype.tableName = function (connectorType) {
var settings = this.settings; var settings = this.settings;
if(settings[connectorType]) { if (settings[connectorType]) {
return settings[connectorType].table || settings[connectorType].tableName || this.name; return settings[connectorType].table || settings[connectorType].tableName || this.name;
} else { } else {
return this.name; return this.name;
@ -70,12 +69,12 @@ ModelDefinition.prototype.tableName = function (connectorType) {
* @returns {String} columnName * @returns {String} columnName
*/ */
ModelDefinition.prototype.columnName = function (connectorType, propertyName) { ModelDefinition.prototype.columnName = function (connectorType, propertyName) {
if(!propertyName) { if (!propertyName) {
return propertyName; return propertyName;
} }
this.build(); this.build();
var property = this.properties[propertyName]; var property = this.properties[propertyName];
if(property && property[connectorType]) { if (property && property[connectorType]) {
return property[connectorType].column || property[connectorType].columnName || propertyName; return property[connectorType].column || property[connectorType].columnName || propertyName;
} else { } else {
return propertyName; return propertyName;
@ -89,12 +88,12 @@ ModelDefinition.prototype.columnName = function (connectorType, propertyName) {
* @returns {Object} column metadata * @returns {Object} column metadata
*/ */
ModelDefinition.prototype.columnMetadata = function (connectorType, propertyName) { ModelDefinition.prototype.columnMetadata = function (connectorType, propertyName) {
if(!propertyName) { if (!propertyName) {
return propertyName; return propertyName;
} }
this.build(); this.build();
var property = this.properties[propertyName]; var property = this.properties[propertyName];
if(property && property[connectorType]) { if (property && property[connectorType]) {
return property[connectorType]; return property[connectorType];
} else { } else {
return null; return null;
@ -110,8 +109,8 @@ ModelDefinition.prototype.columnNames = function (connectorType) {
this.build(); this.build();
var props = this.properties; var props = this.properties;
var cols = []; var cols = [];
for(var p in props) { for (var p in props) {
if(props[p][connectorType]) { if (props[p][connectorType]) {
cols.push(property[connectorType].column || props[p][connectorType].columnName || p); cols.push(property[connectorType].column || props[p][connectorType].columnName || p);
} else { } else {
cols.push(p); cols.push(p);
@ -125,7 +124,7 @@ ModelDefinition.prototype.columnNames = function (connectorType) {
* @returns {Object[]} property name/index for IDs * @returns {Object[]} property name/index for IDs
*/ */
ModelDefinition.prototype.ids = function () { ModelDefinition.prototype.ids = function () {
if(this._ids) { if (this._ids) {
return this._ids; return this._ids;
} }
var ids = []; var ids = [];
@ -133,10 +132,10 @@ ModelDefinition.prototype.ids = function () {
var props = this.properties; var props = this.properties;
for (var key in props) { for (var key in props) {
var id = props[key].id; var id = props[key].id;
if(!id) { if (!id) {
continue; continue;
} }
if(typeof id !== 'number') { if (typeof id !== 'number') {
id = 1; id = 1;
} }
ids.push({name: key, id: id}); ids.push({name: key, id: id});
@ -153,7 +152,7 @@ ModelDefinition.prototype.ids = function () {
* @param {String} modelName The model name * @param {String} modelName The model name
* @returns {String} columnName for ID * @returns {String} columnName for ID
*/ */
ModelDefinition.prototype.idColumnName = function(connectorType) { ModelDefinition.prototype.idColumnName = function (connectorType) {
return this.columnName(connectorType, this.idName()); return this.columnName(connectorType, this.idName());
}; };
@ -161,11 +160,12 @@ ModelDefinition.prototype.idColumnName = function(connectorType) {
* Find the ID property name * Find the ID property name
* @returns {String} property name for ID * @returns {String} property name for ID
*/ */
ModelDefinition.prototype.idName = function() { ModelDefinition.prototype.idName = function () {
var id = this.ids()[0]; var id = this.ids()[0];
if(this.properties.id && this.properties.id.id) { if (this.properties.id && this.properties.id.id) {
return 'id'; return 'id';
} else {} } else {
}
return id && id.name; return id && id.name;
}; };
@ -206,7 +206,7 @@ ModelDefinition.prototype.indexes = function () {
* @param {Boolean} force Forcing rebuild * @param {Boolean} force Forcing rebuild
*/ */
ModelDefinition.prototype.build = function (forceRebuild) { ModelDefinition.prototype.build = function (forceRebuild) {
if(forceRebuild) { if (forceRebuild) {
this.properties = null; this.properties = null;
this.relations = []; this.relations = [];
this._ids = null; this._ids = null;
@ -253,19 +253,18 @@ ModelDefinition.prototype.defineProperty = function (propertyName, propertyDefin
this.build(true); this.build(true);
}; };
function isModelClass(cls) { function isModelClass(cls) {
if(!cls) { if (!cls) {
return false; return false;
} }
return cls.prototype instanceof ModelBaseClass; return cls.prototype instanceof ModelBaseClass;
} }
ModelDefinition.prototype.toJSON = function(forceRebuild) { ModelDefinition.prototype.toJSON = function (forceRebuild) {
if(forceRebuild) { if (forceRebuild) {
this.json = null; this.json = null;
} }
if(this.json) { if (this.json) {
return json; return json;
} }
var json = { var json = {
@ -275,17 +274,17 @@ ModelDefinition.prototype.toJSON = function(forceRebuild) {
}; };
this.build(forceRebuild); this.build(forceRebuild);
var mapper = function(val) { var mapper = function (val) {
if(val === undefined || val === null) { if (val === undefined || val === null) {
return val; return val;
} }
if('function' === typeof val.toJSON) { if ('function' === typeof val.toJSON) {
// The value has its own toJSON() object // The value has its own toJSON() object
return val.toJSON(); return val.toJSON();
} }
if('function' === typeof val) { if ('function' === typeof val) {
if(isModelClass(val)) { if (isModelClass(val)) {
if(val.settings && val.settings.anonymous) { if (val.settings && val.settings.anonymous) {
return val.definition && val.definition.toJSON().properties; return val.definition && val.definition.toJSON().properties;
} else { } else {
return val.modelName; return val.modelName;
@ -296,7 +295,7 @@ ModelDefinition.prototype.toJSON = function(forceRebuild) {
return val; return val;
} }
}; };
for(var p in this.properties) { for (var p in this.properties) {
json.properties[p] = traverse(this.properties[p]).map(mapper); json.properties[p] = traverse(this.properties[p]).map(mapper);
} }
this.json = json; this.json = json;

View File

@ -90,26 +90,26 @@ ModelBaseClass.prototype._initProperties = function (data, applySetters) {
this.__data[ctor.relations[i].keyFrom] = this.__dataWas[i] = data[i][ctor.relations[i].keyTo]; this.__data[ctor.relations[i].keyFrom] = this.__dataWas[i] = data[i][ctor.relations[i].keyTo];
this.__cachedRelations[i] = data[i]; this.__cachedRelations[i] = data[i];
} else { } else {
if(strict === false) { if (strict === false) {
this.__data[i] = this.__dataWas[i] = clone(data[i]); this.__data[i] = this.__dataWas[i] = clone(data[i]);
} else if(strict === 'throw') { } else if (strict === 'throw') {
throw new Error('Unknown property: ' + i); throw new Error('Unknown property: ' + i);
} }
} }
} }
if (applySetters === true) { if (applySetters === true) {
for(var propertyName in data) { for (var propertyName in data) {
if((propertyName in properties) || (propertyName in ctor.relations)) { if ((propertyName in properties) || (propertyName in ctor.relations)) {
self[propertyName] = self.__data[propertyName] || data[propertyName]; self[propertyName] = self.__data[propertyName] || data[propertyName];
} }
} }
} }
// Set the unknown properties as properties to the object // Set the unknown properties as properties to the object
if(strict === false) { if (strict === false) {
for(var propertyName in data) { for (var propertyName in data) {
if(!(propertyName in properties)) { if (!(propertyName in properties)) {
self[propertyName] = self.__data[propertyName] || data[propertyName]; self[propertyName] = self.__data[propertyName] || data[propertyName];
} }
} }
@ -138,7 +138,7 @@ ModelBaseClass.prototype._initProperties = function (data, applySetters) {
} }
} }
if (type.name === 'Array' || Array.isArray(type)) { if (type.name === 'Array' || Array.isArray(type)) {
if(!(self.__data[propertyName] instanceof List)) { if (!(self.__data[propertyName] instanceof List)) {
self.__data[propertyName] = new List(self.__data[propertyName], type, self); self.__data[propertyName] = new List(self.__data[propertyName], type, self);
} }
} }
@ -172,7 +172,7 @@ ModelBaseClass.defineProperty = function (prop, params) {
ModelBaseClass.getPropertyType = function (propName) { ModelBaseClass.getPropertyType = function (propName) {
var prop = this.definition.properties[propName]; var prop = this.definition.properties[propName];
if(!prop) { if (!prop) {
// The property is not part of the definition // The property is not part of the definition
return null; return null;
} }
@ -213,7 +213,7 @@ ModelBaseClass.prototype.toObject = function (onlySchema) {
if (self[propertyName] instanceof List) { if (self[propertyName] instanceof List) {
data[propertyName] = self[propertyName].toObject(!schemaLess); data[propertyName] = self[propertyName].toObject(!schemaLess);
} else if (self.__data.hasOwnProperty(propertyName)) { } else if (self.__data.hasOwnProperty(propertyName)) {
if(self[propertyName] !== undefined && self[propertyName]!== null && self[propertyName].toObject) { if (self[propertyName] !== undefined && self[propertyName] !== null && self[propertyName].toObject) {
data[propertyName] = self[propertyName].toObject(!schemaLess); data[propertyName] = self[propertyName].toObject(!schemaLess);
} else { } else {
data[propertyName] = self[propertyName]; data[propertyName] = self[propertyName];
@ -224,10 +224,10 @@ ModelBaseClass.prototype.toObject = function (onlySchema) {
}); });
if (schemaLess) { if (schemaLess) {
for(var propertyName in self.__data) { for (var propertyName in self.__data) {
if (!data.hasOwnProperty(propertyName)) { if (!data.hasOwnProperty(propertyName)) {
var val = self.hasOwnProperty(propertyName) ? self[propertyName] : self.__data[propertyName]; var val = self.hasOwnProperty(propertyName) ? self[propertyName] : self.__data[propertyName];
if(val !== undefined && val!== null && val.toObject) { if (val !== undefined && val !== null && val.toObject) {
data[propertyName] = val.toObject(!schemaLess); data[propertyName] = val.toObject(!schemaLess);
} else { } else {
data[propertyName] = val; data[propertyName] = val;
@ -248,7 +248,7 @@ ModelBaseClass.prototype.toJSON = function () {
}; };
ModelBaseClass.prototype.fromObject = function (obj) { ModelBaseClass.prototype.fromObject = function (obj) {
for(var key in obj) { for (var key in obj) {
this[key] = obj[key]; this[key] = obj[key];
} }
}; };
@ -271,7 +271,7 @@ ModelBaseClass.prototype.propertyChanged = function propertyChanged(propertyName
*/ */
ModelBaseClass.prototype.reset = function () { ModelBaseClass.prototype.reset = function () {
var obj = this; var obj = this;
for(var k in obj) { for (var k in obj) {
if (k !== 'id' && !obj.constructor.dataSource.definitions[obj.constructor.modelName].properties[k]) { if (k !== 'id' && !obj.constructor.dataSource.definitions[obj.constructor.modelName].properties[k]) {
delete obj[k]; delete obj[k];
} }
@ -285,7 +285,7 @@ ModelBaseClass.prototype.inspect = function () {
return util.inspect(this.__data, false, 4, true); return util.inspect(this.__data, false, 4, true);
}; };
ModelBaseClass.mixin = function(anotherClass, options) { ModelBaseClass.mixin = function (anotherClass, options) {
return jutil.mixin(this, anotherClass, options); return jutil.mixin(this, anotherClass, options);
}; };

View File

@ -34,7 +34,7 @@ Relation.hasMany = function hasMany(anotherClass, params) {
anotherClass = params.model; anotherClass = params.model;
} else { } else {
var anotherClassName = i8n.singularize(anotherClass).toLowerCase(); var anotherClassName = i8n.singularize(anotherClass).toLowerCase();
for(var name in this.dataSource.modelBuilder.models) { for (var name in this.dataSource.modelBuilder.models) {
if (name.toLowerCase() === anotherClassName) { if (name.toLowerCase() === anotherClassName) {
anotherClass = this.dataSource.modelBuilder.models[name]; anotherClass = this.dataSource.modelBuilder.models[name];
} }
@ -68,17 +68,18 @@ Relation.hasMany = function hasMany(anotherClass, params) {
data = {}; data = {};
} }
if ('function' !== typeof done) { if ('function' !== typeof done) {
done = function() {}; done = function () {
};
} }
var self = this; var self = this;
anotherClass.create(data, function(err, ac) { anotherClass.create(data, function (err, ac) {
if (err) return done(err, ac); if (err) return done(err, ac);
var d = {}; var d = {};
d[params.through.relationNameFor(fk)] = self; d[params.through.relationNameFor(fk)] = self;
d[params.through.relationNameFor(fk2)] = ac; d[params.through.relationNameFor(fk2)] = ac;
params.through.create(d, function(e) { params.through.create(d, function (e) {
if (e) { if (e) {
ac.destroy(function() { ac.destroy(function () {
done(e); done(e);
}); });
} else { } else {
@ -87,7 +88,7 @@ Relation.hasMany = function hasMany(anotherClass, params) {
}); });
}); });
}; };
scopeMethods.add = function(acInst, done) { scopeMethods.add = function (acInst, done) {
var data = {}; var data = {};
var query = {}; var query = {};
query[fk] = this[idName]; query[fk] = this[idName];
@ -96,10 +97,10 @@ Relation.hasMany = function hasMany(anotherClass, params) {
data[params.through.relationNameFor(fk2)] = acInst; data[params.through.relationNameFor(fk2)] = acInst;
params.through.findOrCreate({where: query}, data, done); params.through.findOrCreate({where: query}, data, done);
}; };
scopeMethods.remove = function(acInst, done) { scopeMethods.remove = function (acInst, done) {
var q = {}; var q = {};
q[fk2] = acInst[idName] || acInst; q[fk2] = acInst[idName] || acInst;
params.through.findOne({where: q}, function(err, d) { params.through.findOne({where: q}, function (err, d) {
if (err) { if (err) {
return done(err); return done(err);
} }
@ -185,7 +186,7 @@ Relation.belongsTo = function (anotherClass, params) {
anotherClass = params.model; anotherClass = params.model;
} else { } else {
var anotherClassName = anotherClass.toLowerCase(); var anotherClassName = anotherClass.toLowerCase();
for(var name in this.dataSource.modelBuilder.models) { for (var name in this.dataSource.modelBuilder.models) {
if (name.toLowerCase() === anotherClassName) { if (name.toLowerCase() === anotherClassName) {
anotherClass = this.dataSource.modelBuilder.models[name]; anotherClass = this.dataSource.modelBuilder.models[name];
} }
@ -213,7 +214,7 @@ Relation.belongsTo = function (anotherClass, params) {
cb(null, null); cb(null, null);
return; return;
} }
anotherClass.findById(id, function (err,inst) { anotherClass.findById(id, function (err, inst) {
if (err) return cb(err); if (err) return cb(err);
if (!inst) return cb(null, null); if (!inst) return cb(null, null);
if (inst[idName] === this[fk]) { if (inst[idName] === this[fk]) {
@ -241,7 +242,7 @@ Relation.belongsTo = function (anotherClass, params) {
this.__cachedRelations[methodName] = p; this.__cachedRelations[methodName] = p;
} else if (typeof p === 'function') { // acts as async getter } else if (typeof p === 'function') { // acts as async getter
if (typeof cachedValue === 'undefined') { if (typeof cachedValue === 'undefined') {
this.__finders__[methodName].apply(self, [this[fk], function(err, inst) { this.__finders__[methodName].apply(self, [this[fk], function (err, inst) {
if (!err) { if (!err) {
self.__cachedRelations[methodName] = inst; self.__cachedRelations[methodName] = inst;
} }

View File

@ -57,7 +57,7 @@ function defineScope(cls, targetClass, name, params, methods) {
if (!this.__cachedRelations || (typeof this.__cachedRelations[name] == 'undefined') || actualRefresh) { if (!this.__cachedRelations || (typeof this.__cachedRelations[name] == 'undefined') || actualRefresh) {
var self = this; var self = this;
var params = mergeParams(actualCond, caller._scope); var params = mergeParams(actualCond, caller._scope);
return targetClass.find(params, function(err, data) { return targetClass.find(params, function (err, data) {
if (!err && saveOnCache) { if (!err && saveOnCache) {
if (!self.__cachedRelations) { if (!self.__cachedRelations) {
self.__cachedRelations = {}; self.__cachedRelations = {};
@ -94,7 +94,7 @@ function defineScope(cls, targetClass, name, params, methods) {
}); });
// Wrap the property into a function for remoting // Wrap the property into a function for remoting
var fn = function() { var fn = function () {
// primaryObject.scopeName, such as user.accounts // primaryObject.scopeName, such as user.accounts
var f = this[name]; var f = this[name];
// set receiver to be the scope property whose value is a function // set receiver to be the scope property whose value is a function
@ -109,7 +109,7 @@ function defineScope(cls, targetClass, name, params, methods) {
cls['__get__' + name] = fn; cls['__get__' + name] = fn;
var fn_create = function() { var fn_create = function () {
var f = this[name].create; var f = this[name].create;
f.apply(this[name], arguments); f.apply(this[name], arguments);
}; };
@ -122,7 +122,7 @@ function defineScope(cls, targetClass, name, params, methods) {
cls['__create__' + name] = fn_create; cls['__create__' + name] = fn_create;
var fn_delete = function() { var fn_delete = function () {
var f = this[name].destroyAll; var f = this[name].destroyAll;
f.apply(this[name], arguments); f.apply(this[name], arguments);
}; };
@ -135,7 +135,7 @@ function defineScope(cls, targetClass, name, params, methods) {
// and it should have create/build methods with binded thisModelNameId param // and it should have create/build methods with binded thisModelNameId param
function build(data) { function build(data) {
return new targetClass(mergeParams(this._scope, {where:data || {}}).where); return new targetClass(mergeParams(this._scope, {where: data || {}}).where);
} }
function create(data, cb) { function create(data, cb) {
@ -157,14 +157,14 @@ function defineScope(cls, targetClass, name, params, methods) {
if (err) { if (err) {
cb(err); cb(err);
} else { } else {
(function loopOfDestruction (data) { (function loopOfDestruction(data) {
if(data.length > 0) { if (data.length > 0) {
data.shift().destroy(function(err) { data.shift().destroy(function (err) {
if(err && cb) cb(err); if (err && cb) cb(err);
loopOfDestruction(data); loopOfDestruction(data);
}); });
} else { } else {
if(cb) cb(); if (cb) cb();
} }
}(data)); }(data));
} }

View File

@ -34,7 +34,6 @@ BaseSQL.prototype.queryOne = function (sql, callback) {
}); });
}; };
/** /**
* Get the table name for a given model * Get the table name for a given model
* @param {String} model The model name * @param {String} model The model name
@ -43,7 +42,7 @@ BaseSQL.prototype.queryOne = function (sql, callback) {
BaseSQL.prototype.table = function (model) { BaseSQL.prototype.table = function (model) {
var name = this.getDataSource(model).tableName(model); var name = this.getDataSource(model).tableName(model);
var dbName = this.dbName; var dbName = this.dbName;
if(typeof dbName === 'function') { if (typeof dbName === 'function') {
name = dbName(name); name = dbName(name);
} }
return name; return name;
@ -58,7 +57,7 @@ BaseSQL.prototype.table = function (model) {
BaseSQL.prototype.column = function (model, property) { BaseSQL.prototype.column = function (model, property) {
var name = this.getDataSource(model).columnName(model, property); var name = this.getDataSource(model).columnName(model, property);
var dbName = this.dbName; var dbName = this.dbName;
if(typeof dbName === 'function') { if (typeof dbName === 'function') {
name = dbName(name); name = dbName(name);
} }
return name; return name;
@ -82,8 +81,8 @@ BaseSQL.prototype.columnMetadata = function (model, property) {
*/ */
BaseSQL.prototype.propertyName = function (model, column) { BaseSQL.prototype.propertyName = function (model, column) {
var props = this._models[model].properties; var props = this._models[model].properties;
for(var p in props) { for (var p in props) {
if(this.column(model, p) === column) { if (this.column(model, p) === column) {
return p; return p;
} }
} }
@ -96,9 +95,10 @@ BaseSQL.prototype.propertyName = function (model, column) {
* @returns {String} The column name * @returns {String} The column name
*/ */
BaseSQL.prototype.idColumn = function (model) { BaseSQL.prototype.idColumn = function (model) {
var name = this.getDataSource(model).idColumnName(model);; var name = this.getDataSource(model).idColumnName(model);
;
var dbName = this.dbName; var dbName = this.dbName;
if(typeof dbName === 'function') { if (typeof dbName === 'function') {
name = dbName(name); name = dbName(name);
} }
return name; return name;
@ -155,7 +155,6 @@ BaseSQL.prototype.save = function (model, data, callback) {
}); });
}; };
/** /**
* Check if a model instance exists for the given id value * Check if a model instance exists for the given id value
* @param {String} model The model name * @param {String} model The model name

View File

@ -58,4 +58,4 @@ module.exports = function (Types) {
Types.registerType(Array); Types.registerType(Array);
Types.registerType(GeoPoint); Types.registerType(GeoPoint);
Types.registerType(Object); Types.registerType(Object);
} };

View File

@ -11,18 +11,20 @@ function safeRequire(module) {
try { try {
return require(module); return require(module);
} catch (e) { } catch (e) {
console.log('Run "npm install loopback-datasource-juggler ' + module + '" command to use loopback-datasource-juggler using ' + module + ' database engine'); console.log('Run "npm install loopback-datasource-juggler ' + module
+ '" command to use loopback-datasource-juggler using ' + module
+ ' database engine');
process.exit(1); process.exit(1);
} }
} }
function fieldsToArray(fields, properties) { function fieldsToArray(fields, properties) {
if(!fields) return; if (!fields) return;
// include all properties by default // include all properties by default
var result = properties; var result = properties;
if(typeof fields === 'string') { if (typeof fields === 'string') {
return [fields]; return [fields];
} }
@ -36,7 +38,7 @@ function fieldsToArray(fields, properties) {
var included = []; var included = [];
var excluded = []; var excluded = [];
var keys = Object.keys(fields); var keys = Object.keys(fields);
if(!keys.length) return; if (!keys.length) return;
keys.forEach(function (k) { keys.forEach(function (k) {
if (fields[k]) { if (fields[k]) {
@ -89,7 +91,8 @@ function removeUndefined(query) {
this.remove(); this.remove();
} }
if (!Array.isArray(x) && (typeof x === 'object' && x !== null && x.constructor !== Object)) { if (!Array.isArray(x) && (typeof x === 'object' && x !== null
&& x.constructor !== Object)) {
// This object is not a plain object // This object is not a plain object
this.update(x, true); // Stop navigating into this object this.update(x, true); // Stop navigating into this object
return x; return x;
@ -108,7 +111,7 @@ var qs = require('qs');
* @returns {Object} The settings object * @returns {Object} The settings object
*/ */
function parseSettings(urlStr) { function parseSettings(urlStr) {
if(!urlStr) { if (!urlStr) {
return {}; return {};
} }
var uri = url.parse(urlStr, false); var uri = url.parse(urlStr, false);
@ -120,9 +123,9 @@ function parseSettings(urlStr) {
settings.password = uri.auth && uri.auth.split(':')[1]; settings.password = uri.auth && uri.auth.split(':')[1];
settings.database = uri.pathname && uri.pathname.split('/')[1]; // remove the leading / settings.database = uri.pathname && uri.pathname.split('/')[1]; // remove the leading /
settings.url = urlStr; settings.url = urlStr;
if(uri.query) { if (uri.query) {
var params = qs.parse(uri.query); var params = qs.parse(uri.query);
for(var p in params) { for (var p in params) {
settings[p] = params[p]; settings[p] = params[p];
} }
} }

View File

@ -348,7 +348,7 @@ Validatable.prototype.isValid = function (callback, data) {
cleanErrors(this); cleanErrors(this);
if (callback) { if (callback) {
this.trigger('validate', function (validationsDone) { this.trigger('validate', function (validationsDone) {
validationsDone.call(inst, function() { validationsDone.call(inst, function () {
callback(valid); callback(valid);
}); });
}); });
@ -382,7 +382,7 @@ Validatable.prototype.isValid = function (callback, data) {
}); });
if (!async) { if (!async) {
validationsDone.call(inst, function() { validationsDone.call(inst, function () {
if (valid) cleanErrors(inst); if (valid) cleanErrors(inst);
if (callback) { if (callback) {
callback(valid); callback(valid);
@ -590,7 +590,7 @@ Errors.prototype.add = function (field, message, code) {
function ErrorCodes(messages) { function ErrorCodes(messages) {
var c = this; var c = this;
Object.keys(messages).forEach(function(field) { Object.keys(messages).forEach(function (field) {
c[field] = messages[field].codes; c[field] = messages[field].codes;
}); });
} }

View File

@ -2,9 +2,9 @@
var should = require('./init.js'); var should = require('./init.js');
var db, User; var db, User;
describe('basic-querying', function() { describe('basic-querying', function () {
before(function(done) { before(function (done) {
db = getSchema(); db = getSchema();
User = db.define('User', { User = db.define('User', {
@ -18,26 +18,25 @@ describe('basic-querying', function() {
}); });
describe('findById', function () {
describe('findById', function() { before(function (done) {
before(function(done) {
User.destroyAll(done); User.destroyAll(done);
}); });
it('should query by id: not found', function(done) { it('should query by id: not found', function (done) {
User.findById(1, function(err, u) { User.findById(1, function (err, u) {
should.not.exist(u); should.not.exist(u);
should.not.exist(err); should.not.exist(err);
done(); done();
}); });
}); });
it('should query by id: found', function(done) { it('should query by id: found', function (done) {
User.create(function(err, u) { User.create(function (err, u) {
should.not.exist(err); should.not.exist(err);
should.exist(u.id); should.exist(u.id);
User.findById(u.id, function(err, u) { User.findById(u.id, function (err, u) {
should.exist(u); should.exist(u);
should.not.exist(err); should.not.exist(err);
u.should.be.an.instanceOf(User); u.should.be.an.instanceOf(User);
@ -48,12 +47,12 @@ describe('basic-querying', function() {
}); });
describe('find', function() { describe('find', function () {
before(seed); before(seed);
it('should query collection', function(done) { it('should query collection', function (done) {
User.find(function(err, users) { User.find(function (err, users) {
should.exists(users); should.exists(users);
should.not.exists(err); should.not.exists(err);
users.should.have.lengthOf(6); users.should.have.lengthOf(6);
@ -61,8 +60,8 @@ describe('basic-querying', function() {
}); });
}); });
it('should query limited collection', function(done) { it('should query limited collection', function (done) {
User.find({limit: 3}, function(err, users) { User.find({limit: 3}, function (err, users) {
should.exists(users); should.exists(users);
should.not.exists(err); should.not.exists(err);
users.should.have.lengthOf(3); users.should.have.lengthOf(3);
@ -70,8 +69,8 @@ describe('basic-querying', function() {
}); });
}); });
it('should query offset collection with limit', function(done) { it('should query offset collection with limit', function (done) {
User.find({skip: 1, limit: 4}, function(err, users) { User.find({skip: 1, limit: 4}, function (err, users) {
should.exists(users); should.exists(users);
should.not.exists(err); should.not.exists(err);
users.should.have.lengthOf(4); users.should.have.lengthOf(4);
@ -79,8 +78,8 @@ describe('basic-querying', function() {
}); });
}); });
it('should query filtered collection', function(done) { it('should query filtered collection', function (done) {
User.find({where: {role: 'lead'}}, function(err, users) { User.find({where: {role: 'lead'}}, function (err, users) {
should.exists(users); should.exists(users);
should.not.exists(err); should.not.exists(err);
users.should.have.lengthOf(2); users.should.have.lengthOf(2);
@ -88,30 +87,30 @@ describe('basic-querying', function() {
}); });
}); });
it('should query collection sorted by numeric field', function(done) { it('should query collection sorted by numeric field', function (done) {
User.find({order: 'order'}, function(err, users) { User.find({order: 'order'}, function (err, users) {
should.exists(users); should.exists(users);
should.not.exists(err); should.not.exists(err);
users.forEach(function(u, i) { users.forEach(function (u, i) {
u.order.should.eql(i + 1); u.order.should.eql(i + 1);
}); });
done(); done();
}); });
}); });
it('should query collection desc sorted by numeric field', function(done) { it('should query collection desc sorted by numeric field', function (done) {
User.find({order: 'order DESC'}, function(err, users) { User.find({order: 'order DESC'}, function (err, users) {
should.exists(users); should.exists(users);
should.not.exists(err); should.not.exists(err);
users.forEach(function(u, i) { users.forEach(function (u, i) {
u.order.should.eql(users.length - i); u.order.should.eql(users.length - i);
}); });
done(); done();
}); });
}); });
it('should query collection sorted by string field', function(done) { it('should query collection sorted by string field', function (done) {
User.find({order: 'name'}, function(err, users) { User.find({order: 'name'}, function (err, users) {
should.exists(users); should.exists(users);
should.not.exists(err); should.not.exists(err);
users.shift().name.should.equal('George Harrison'); users.shift().name.should.equal('George Harrison');
@ -121,8 +120,8 @@ describe('basic-querying', function() {
}); });
}); });
it('should query collection desc sorted by string field', function(done) { it('should query collection desc sorted by string field', function (done) {
User.find({order: 'name DESC'}, function(err, users) { User.find({order: 'name DESC'}, function (err, users) {
should.exists(users); should.exists(users);
should.not.exists(err); should.not.exists(err);
users.pop().name.should.equal('George Harrison'); users.pop().name.should.equal('George Harrison');
@ -132,7 +131,7 @@ describe('basic-querying', function() {
}); });
}); });
it('should only include fields as specified', function(done) { it('should only include fields as specified', function (done) {
var remaining = 0; var remaining = 0;
function sample(fields) { function sample(fields) {
@ -140,14 +139,14 @@ describe('basic-querying', function() {
return { return {
expect: function (arr) { expect: function (arr) {
remaining++; remaining++;
User.find({fields: fields}, function(err, users) { User.find({fields: fields}, function (err, users) {
remaining--; remaining--;
if(err) return done(err); if (err) return done(err);
should.exists(users); should.exists(users);
if(remaining === 0) { if (remaining === 0) {
done(); done();
} }
@ -157,11 +156,11 @@ describe('basic-querying', function() {
Object.keys(obj) Object.keys(obj)
.forEach(function (key) { .forEach(function (key) {
// if the obj has an unexpected value // if the obj has an unexpected value
if(obj[key] !== undefined && arr.indexOf(key) === -1) { if (obj[key] !== undefined && arr.indexOf(key) === -1) {
console.log('Given fields:', fields); console.log('Given fields:', fields);
console.log('Got:', key, obj[key]); console.log('Got:', key, obj[key]);
console.log('Expected:', arr); console.log('Expected:', arr);
throw new Error('should not include data for key: '+ key); throw new Error('should not include data for key: ' + key);
} }
}); });
}); });
@ -181,12 +180,12 @@ describe('basic-querying', function() {
}); });
describe('count', function() { describe('count', function () {
before(seed); before(seed);
it('should query total count', function(done) { it('should query total count', function (done) {
User.count(function(err, n) { User.count(function (err, n) {
should.not.exist(err); should.not.exist(err);
should.exist(n); should.exist(n);
n.should.equal(6); n.should.equal(6);
@ -194,8 +193,8 @@ describe('basic-querying', function() {
}); });
}); });
it('should query filtered count', function(done) { it('should query filtered count', function (done) {
User.count({role: 'lead'}, function(err, n) { User.count({role: 'lead'}, function (err, n) {
should.not.exist(err); should.not.exist(err);
should.exist(n); should.exist(n);
n.should.equal(2); n.should.equal(2);
@ -204,13 +203,13 @@ describe('basic-querying', function() {
}); });
}); });
describe('findOne', function() { describe('findOne', function () {
before(seed); before(seed);
it('should find first record (default sort by id)', function(done) { it('should find first record (default sort by id)', function (done) {
User.all({order: 'id'}, function(err, users) { User.all({order: 'id'}, function (err, users) {
User.findOne(function(e, u) { User.findOne(function (e, u) {
should.not.exist(e); should.not.exist(e);
should.exist(u); should.exist(u);
u.id.toString().should.equal(users[0].id.toString()); u.id.toString().should.equal(users[0].id.toString());
@ -219,8 +218,8 @@ describe('basic-querying', function() {
}); });
}); });
it('should find first record', function(done) { it('should find first record', function (done) {
User.findOne({order: 'order'}, function(e, u) { User.findOne({order: 'order'}, function (e, u) {
should.not.exist(e); should.not.exist(e);
should.exist(u); should.exist(u);
u.order.should.equal(1); u.order.should.equal(1);
@ -229,8 +228,8 @@ describe('basic-querying', function() {
}); });
}); });
it('should find last record', function(done) { it('should find last record', function (done) {
User.findOne({order: 'order DESC'}, function(e, u) { User.findOne({order: 'order DESC'}, function (e, u) {
should.not.exist(e); should.not.exist(e);
should.exist(u); should.exist(u);
u.order.should.equal(6); u.order.should.equal(6);
@ -239,11 +238,11 @@ describe('basic-querying', function() {
}); });
}); });
it('should find last record in filtered set', function(done) { it('should find last record in filtered set', function (done) {
User.findOne({ User.findOne({
where: {role: 'lead'}, where: {role: 'lead'},
order: 'order DESC' order: 'order DESC'
}, function(e, u) { }, function (e, u) {
should.not.exist(e); should.not.exist(e);
should.exist(u); should.exist(u);
u.order.should.equal(2); u.order.should.equal(2);
@ -252,9 +251,9 @@ describe('basic-querying', function() {
}); });
}); });
it('should work even when find by id', function(done) { it('should work even when find by id', function (done) {
User.findOne(function(e, u) { User.findOne(function (e, u) {
User.findOne({where: {id: u.id}}, function(err, user) { User.findOne({where: {id: u.id}}, function (err, user) {
should.not.exist(err); should.not.exist(err);
should.exist(user); should.exist(user);
done(); done();
@ -264,13 +263,13 @@ describe('basic-querying', function() {
}); });
describe('exists', function() { describe('exists', function () {
before(seed); before(seed);
it('should check whether record exist', function(done) { it('should check whether record exist', function (done) {
User.findOne(function(e, u) { User.findOne(function (e, u) {
User.exists(u.id, function(err, exists) { User.exists(u.id, function (err, exists) {
should.not.exist(err); should.not.exist(err);
should.exist(exists); should.exist(exists);
exists.should.be.ok; exists.should.be.ok;
@ -279,9 +278,9 @@ describe('basic-querying', function() {
}); });
}); });
it('should check whether record not exist', function(done) { it('should check whether record not exist', function (done) {
User.destroyAll(function() { User.destroyAll(function () {
User.exists(42, function(err, exists) { User.exists(42, function (err, exists) {
should.not.exist(err); should.not.exist(err);
exists.should.not.be.ok; exists.should.not.be.ok;
done(); done();
@ -291,16 +290,16 @@ describe('basic-querying', function() {
}); });
describe('destroyAll with where option', function() { describe('destroyAll with where option', function () {
before(seed); before(seed);
it('should only delete instances that satisfy the where condition', function(done) { it('should only delete instances that satisfy the where condition', function (done) {
User.destroyAll({name: 'John Lennon'}, function() { User.destroyAll({name: 'John Lennon'}, function () {
User.find({where: {name: 'John Lennon'}}, function(err, data) { User.find({where: {name: 'John Lennon'}}, function (err, data) {
should.not.exist(err); should.not.exist(err);
data.length.should.equal(0); data.length.should.equal(0);
User.find({where: {name: 'Paul McCartney'}}, function(err, data) { User.find({where: {name: 'Paul McCartney'}}, function (err, data) {
should.not.exist(err); should.not.exist(err);
data.length.should.equal(1); data.length.should.equal(1);
done(); done();
@ -311,8 +310,6 @@ describe('basic-querying', function() {
}); });
}); });
function seed(done) { function seed(done) {
@ -323,7 +320,8 @@ function seed(done) {
email: 'john@b3atl3s.co.uk', email: 'john@b3atl3s.co.uk',
role: 'lead', role: 'lead',
order: 2 order: 2
}, { },
{
name: 'Paul McCartney', name: 'Paul McCartney',
email: 'paul@b3atl3s.co.uk', email: 'paul@b3atl3s.co.uk',
role: 'lead', role: 'lead',
@ -334,8 +332,8 @@ function seed(done) {
{name: 'Pete Best', order: 4}, {name: 'Pete Best', order: 4},
{name: 'Stuart Sutcliffe', order: 3} {name: 'Stuart Sutcliffe', order: 3}
]; ];
User.destroyAll(function() { User.destroyAll(function () {
beatles.forEach(function(beatle) { beatles.forEach(function (beatle) {
User.create(beatle, ok); User.create(beatle, ok);
}); });
}); });

View File

@ -1,4 +1,3 @@
var Schema = require('../index').Schema; var Schema = require('../index').Schema;
var Text = Schema.Text; var Text = Schema.Text;
@ -72,6 +71,7 @@ function clearAndCreate(model, data, callback) {
}); });
var itemIndex = 0; var itemIndex = 0;
function nextItem(err, lastItem) { function nextItem(err, lastItem) {
if (lastItem !== null) { if (lastItem !== null) {
createdItems.push(lastItem); createdItems.push(lastItem);
@ -103,12 +103,12 @@ function testOrm(dataSource) {
}); });
Dog = dataSource.define('Dog', { Dog = dataSource.define('Dog', {
name : { type: String, limit: 64, allowNull: false } name: { type: String, limit: 64, allowNull: false }
}); });
Log = dataSource.define('Log', { Log = dataSource.define('Log', {
ownerId : { type: Number, allowNull: true }, ownerId: { type: Number, allowNull: true },
name : { type: String, limit: 64, allowNull: false } name: { type: String, limit: 64, allowNull: false }
}); });
Log.belongsTo(Dog, {as: 'owner', foreignKey: 'ownerId'}); Log.belongsTo(Dog, {as: 'owner', foreignKey: 'ownerId'});
@ -125,13 +125,17 @@ function testOrm(dataSource) {
title: { type: String, length: 255, index: true }, title: { type: String, length: 255, index: true },
subject: { type: String }, subject: { type: String },
content: { type: Text }, content: { type: Text },
date: { type: Date, default: function () { return new Date }, index: true }, date: { type: Date, default: function () {
return new Date
}, index: true },
published: { type: Boolean, default: false, index: true }, published: { type: Boolean, default: false, index: true },
likes: [], likes: [],
related: [RelatedPost] related: [RelatedPost]
}, {table: 'posts'}); }, {table: 'posts'});
function RelatedPost() { } function RelatedPost() {
}
RelatedPost.prototype.someMethod = function () { RelatedPost.prototype.someMethod = function () {
return this.parent; return this.parent;
}; };
@ -417,7 +421,6 @@ function testOrm(dataSource) {
test.done(); test.done();
}); });
it('should handle hasMany relationship', function (test) { it('should handle hasMany relationship', function (test) {
User.create(function (err, u) { User.create(function (err, u) {
if (err) return console.log(err); if (err) return console.log(err);
@ -434,23 +437,23 @@ function testOrm(dataSource) {
}); });
}); });
it('should navigate variations of belongsTo regardless of column name', function(test){ it('should navigate variations of belongsTo regardless of column name', function (test) {
Dog.create({name: 'theDog'}, function(err, obj){ Dog.create({name: 'theDog'}, function (err, obj) {
test.ok(obj instanceof Dog); test.ok(obj instanceof Dog);
Log.create({name: 'theLog', ownerId: obj.id}, function(err, obj){ Log.create({name: 'theLog', ownerId: obj.id}, function (err, obj) {
test.ok(obj instanceof Log); test.ok(obj instanceof Log);
obj.owner(function(err, obj){ obj.owner(function (err, obj) {
test.ok(!err, 'Should not have an error.'); // Before cba174b this would be 'Error: Permission denied' test.ok(!err, 'Should not have an error.'); // Before cba174b this would be 'Error: Permission denied'
if(err){ if (err) {
console.log('Found: ' + err); console.log('Found: ' + err);
} }
test.ok(obj, 'Should not find null or undefined.'); // Before cba174b this could be null or undefined. test.ok(obj, 'Should not find null or undefined.'); // Before cba174b this could be null or undefined.
test.ok(obj instanceof Dog, 'Should find a Dog.'); test.ok(obj instanceof Dog, 'Should find a Dog.');
if(obj){ // Since test won't stop on fail, have to check before accessing obj.name. if (obj) { // Since test won't stop on fail, have to check before accessing obj.name.
test.ok(obj.name, 'Should have a name.'); test.ok(obj.name, 'Should have a name.');
} }
if(obj && obj.name){ if (obj && obj.name) {
test.equal(obj.name, 'theDog', 'The owner of theLog is theDog.'); test.equal(obj.name, 'theDog', 'The owner of theLog is theDog.');
} }
test.done(); test.done();
@ -483,15 +486,15 @@ function testOrm(dataSource) {
var post = posts[i]; var post = posts[i];
if (post.userId) { if (post.userId) {
// We could get the user with belongs to relationship but it is better if there is no interactions. // We could get the user with belongs to relationship but it is better if there is no interactions.
User.findById(post.userId, function(err, user) { User.findById(post.userId, function (err, user) {
User.create(function(err, voidUser) { User.create(function (err, voidUser) {
Post.create({userId: user.id}, function() { Post.create({userId: user.id}, function () {
// There can't be any concurrency because we are counting requests // There can't be any concurrency because we are counting requests
// We are first testing cases when user has posts // We are first testing cases when user has posts
user.posts(function(err, data) { user.posts(function (err, data) {
var nbInitialRequests = nbSchemaRequests; var nbInitialRequests = nbSchemaRequests;
user.posts(function(err, data2) { user.posts(function (err, data2) {
test.equal(data.length, 2, 'There should be 2 posts.'); test.equal(data.length, 2, 'There should be 2 posts.');
test.equal(data.length, data2.length, 'Posts should be the same, since we are loading on the same object.'); test.equal(data.length, data2.length, 'Posts should be the same, since we are loading on the same object.');
requestsAreCounted && test.equal(nbInitialRequests, nbSchemaRequests, 'There should not be any request because value is cached.'); requestsAreCounted && test.equal(nbInitialRequests, nbSchemaRequests, 'There should not be any request because value is cached.');
@ -499,23 +502,23 @@ function testOrm(dataSource) {
if (dataSource.name === 'mongodb') { // for the moment mongodb doesn\'t support additional conditions on hasMany relations (see above) if (dataSource.name === 'mongodb') { // for the moment mongodb doesn\'t support additional conditions on hasMany relations (see above)
test.done(); test.done();
} else { } else {
user.posts({where: {id: data[0].id}}, function(err, data) { user.posts({where: {id: data[0].id}}, function (err, data) {
test.equal(data.length, 1, 'There should be only one post.'); test.equal(data.length, 1, 'There should be only one post.');
requestsAreCounted && test.equal(nbInitialRequests + 1, nbSchemaRequests, 'There should be one additional request since we added conditions.'); requestsAreCounted && test.equal(nbInitialRequests + 1, nbSchemaRequests, 'There should be one additional request since we added conditions.');
user.posts(function(err, data) { user.posts(function (err, data) {
test.equal(data.length, 2, 'Previous get shouldn\'t have changed cached value though, since there was additional conditions.'); test.equal(data.length, 2, 'Previous get shouldn\'t have changed cached value though, since there was additional conditions.');
requestsAreCounted && test.equal(nbInitialRequests + 1, nbSchemaRequests, 'There should not be any request because value is cached.'); requestsAreCounted && test.equal(nbInitialRequests + 1, nbSchemaRequests, 'There should not be any request because value is cached.');
// We are now testing cases when user doesn't have any post // We are now testing cases when user doesn't have any post
voidUser.posts(function(err, data) { voidUser.posts(function (err, data) {
var nbInitialRequests = nbSchemaRequests; var nbInitialRequests = nbSchemaRequests;
voidUser.posts(function(err, data2) { voidUser.posts(function (err, data2) {
test.equal(data.length, 0, 'There shouldn\'t be any posts (1/2).'); test.equal(data.length, 0, 'There shouldn\'t be any posts (1/2).');
test.equal(data2.length, 0, 'There shouldn\'t be any posts (2/2).'); test.equal(data2.length, 0, 'There shouldn\'t be any posts (2/2).');
requestsAreCounted && test.equal(nbInitialRequests, nbSchemaRequests, 'There should not be any request because value is cached.'); requestsAreCounted && test.equal(nbInitialRequests, nbSchemaRequests, 'There should not be any request because value is cached.');
voidUser.posts(true, function(err, data3) { voidUser.posts(true, function (err, data3) {
test.equal(data3.length, 0, 'There shouldn\'t be any posts.'); test.equal(data3.length, 0, 'There shouldn\'t be any posts.');
requestsAreCounted && test.equal(nbInitialRequests + 1, nbSchemaRequests, 'There should be one additional request since we forced refresh.'); requestsAreCounted && test.equal(nbInitialRequests + 1, nbSchemaRequests, 'There should be one additional request since we forced refresh.');
@ -588,15 +591,17 @@ function testOrm(dataSource) {
}); });
it('should handle ORDER clause', function (test) { it('should handle ORDER clause', function (test) {
var titles = [ { title: 'Title A', subject: "B" }, var titles = [
{ title: 'Title A', subject: "B" },
{ title: 'Title Z', subject: "A" }, { title: 'Title Z', subject: "A" },
{ title: 'Title M', subject: "C" }, { title: 'Title M', subject: "C" },
{ title: 'Title A', subject: "A" }, { title: 'Title A', subject: "A" },
{ title: 'Title B', subject: "A" }, { title: 'Title B', subject: "A" },
{ title: 'Title C', subject: "D" }]; { title: 'Title C', subject: "D" }
];
var isRedis = Post.dataSource.name === 'redis'; var isRedis = Post.dataSource.name === 'redis';
var dates = isRedis ? [ 5, 9, 0, 17, 10, 9 ] : [ var dates = isRedis ? [ 5, 9, 0, 17, 10, 9 ] : [
new Date(1000 * 5 ), new Date(1000 * 5),
new Date(1000 * 9), new Date(1000 * 9),
new Date(1000 * 0), new Date(1000 * 0),
new Date(1000 * 17), new Date(1000 * 17),
@ -608,6 +613,7 @@ function testOrm(dataSource) {
}); });
var i = 0, tests = 0; var i = 0, tests = 0;
function done(err, obj) { function done(err, obj) {
if (++i === titles.length) { if (++i === titles.length) {
doFilterAndSortTest(); doFilterAndSortTest();
@ -686,7 +692,7 @@ function testOrm(dataSource) {
function doMultipleSortTest() { function doMultipleSortTest() {
tests += 1; tests += 1;
Post.all({order: "title ASC, subject ASC"}, function(err, posts) { Post.all({order: "title ASC, subject ASC"}, function (err, posts) {
if (err) console.log(err); if (err) console.log(err);
test.equal(posts.length, 6); test.equal(posts.length, 6);
test.equal(posts[0].title, "Title A"); test.equal(posts[0].title, "Title A");
@ -700,12 +706,12 @@ function testOrm(dataSource) {
function doMultipleReverseSortTest() { function doMultipleReverseSortTest() {
tests += 1; tests += 1;
Post.all({order: "title ASC, subject DESC"}, function(err, posts) { Post.all({order: "title ASC, subject DESC"}, function (err, posts) {
if (err) console.log(err); if (err) console.log(err);
test.equal(posts.length, 6); test.equal(posts.length, 6);
test.equal(posts[0].title, "Title A"); test.equal(posts[0].title, "Title A");
test.equal(posts[0].subject, "B"); test.equal(posts[0].subject, "B");
test.equal(posts[1].title,"Title A"); test.equal(posts[1].title, "Title A");
test.equal(posts[1].subject, "A"); test.equal(posts[1].subject, "A");
test.equal(posts[5].title, "Title Z"); test.equal(posts[5].title, "Title Z");
finished(); finished();
@ -713,6 +719,7 @@ function testOrm(dataSource) {
} }
var fin = 0; var fin = 0;
function finished() { function finished() {
if (++fin === tests) { if (++fin === tests) {
test.done(); test.done();
@ -790,7 +797,6 @@ function testOrm(dataSource) {
// } // }
// }); // });
// if ( // if (
// dataSource.name === 'mysql' || // dataSource.name === 'mysql' ||
// dataSource.name === 'postgres' // dataSource.name === 'postgres'
@ -884,6 +890,7 @@ function testOrm(dataSource) {
}); });
}); });
var tests = 2; var tests = 2;
function done() { function done() {
process.nextTick(function () { process.nextTick(function () {
if (--wait === 0) { if (--wait === 0) {

View File

@ -3,9 +3,9 @@ var should = require('./init.js');
var db, Model; var db, Model;
describe('datatypes', function() { describe('datatypes', function () {
before(function(done){ before(function (done) {
db = getSchema(); db = getSchema();
Model = db.define('Model', { Model = db.define('Model', {
str: String, str: String,
@ -14,17 +14,17 @@ describe('datatypes', function() {
bool: Boolean, bool: Boolean,
list: {type: []}, list: {type: []},
}); });
db.automigrate(function() { db.automigrate(function () {
Model.destroyAll(done); Model.destroyAll(done);
}); });
}); });
it('should keep types when get read data from db', function(done) { it('should keep types when get read data from db', function (done) {
var d = new Date, id; var d = new Date, id;
Model.create({ Model.create({
str: 'hello', date: d, num: '3', bool: 1, list: ['test'] str: 'hello', date: d, num: '3', bool: 1, list: ['test']
}, function(err, m) { }, function (err, m) {
should.not.exist(err); should.not.exist(err);
should.exist(m && m.id); should.exist(m && m.id);
m.str.should.be.a('string'); m.str.should.be.a('string');
@ -36,7 +36,7 @@ describe('datatypes', function() {
function testFind(next) { function testFind(next) {
debugger; debugger;
Model.findById(id, function(err, m) { Model.findById(id, function (err, m) {
should.not.exist(err); should.not.exist(err);
should.exist(m); should.exist(m);
m.str.should.be.a('string'); m.str.should.be.a('string');
@ -49,7 +49,7 @@ describe('datatypes', function() {
} }
function testAll() { function testAll() {
Model.findOne(function(err, m) { Model.findOne(function (err, m) {
should.not.exist(err); should.not.exist(err);
should.exist(m); should.exist(m);
m.str.should.be.a('string'); m.str.should.be.a('string');

View File

@ -3,29 +3,29 @@ var should = require('./init.js');
var db = getSchema(); var db = getSchema();
describe('defaults', function() { describe('defaults', function () {
var Server; var Server;
before(function() { before(function () {
Server = db.define('Server', { Server = db.define('Server', {
host: String, host: String,
port: {type: Number, default: 80} port: {type: Number, default: 80}
}); });
}); });
it('should apply defaults on new', function() { it('should apply defaults on new', function () {
var s = new Server; var s = new Server;
s.port.should.equal(80); s.port.should.equal(80);
}); });
it('should apply defaults on create', function(done) { it('should apply defaults on create', function (done) {
Server.create(function(err, s) { Server.create(function (err, s) {
s.port.should.equal(80); s.port.should.equal(80);
done(); done();
}); });
}); });
it('should apply defaults on read', function(done) { it('should apply defaults on read', function (done) {
db.defineProperty('Server', 'host', { db.defineProperty('Server', 'host', {
type: String, type: String,
default: 'localhost' default: 'localhost'

View File

@ -8,9 +8,9 @@ var j = require('../'),
db, User; db, User;
describe('hooks', function() { describe('hooks', function () {
before(function(done) { before(function (done) {
db = getSchema(); db = getSchema();
User = db.define('User', { User = db.define('User', {
@ -23,27 +23,27 @@ describe('hooks', function() {
db.automigrate(done); db.automigrate(done);
}); });
describe('initialize', function() { describe('initialize', function () {
afterEach(function() { afterEach(function () {
User.afterInitialize = null; User.afterInitialize = null;
}); });
it('should be triggered on new', function(done) { it('should be triggered on new', function (done) {
User.afterInitialize = function() { User.afterInitialize = function () {
done(); done();
}; };
new User; new User;
}); });
it('should be triggered on create', function(done) { it('should be triggered on create', function (done) {
var user; var user;
User.afterInitialize = function() { User.afterInitialize = function () {
if (this.name === 'Nickolay') { if (this.name === 'Nickolay') {
this.name += ' Rozental'; this.name += ' Rozental';
} }
}; };
User.create({name: 'Nickolay'}, function(err, u) { User.create({name: 'Nickolay'}, function (err, u) {
u.id.should.be.ok; u.id.should.be.ok;
u.name.should.equal('Nickolay Rozental'); u.name.should.equal('Nickolay Rozental');
done(); done();
@ -52,35 +52,35 @@ describe('hooks', function() {
}); });
describe('create', function() { describe('create', function () {
afterEach(removeHooks('Create')); afterEach(removeHooks('Create'));
it('should be triggered on create', function(done) { it('should be triggered on create', function (done) {
addHooks('Create', done); addHooks('Create', done);
User.create(); User.create();
}); });
it('should not be triggered on new', function() { it('should not be triggered on new', function () {
User.beforeCreate = function(next) { User.beforeCreate = function (next) {
should.fail('This should not be called'); should.fail('This should not be called');
next(); next();
}; };
var u = new User; var u = new User;
}); });
it('should be triggered on new+save', function(done) { it('should be triggered on new+save', function (done) {
addHooks('Create', done); addHooks('Create', done);
(new User).save(); (new User).save();
}); });
it('afterCreate should not be triggered on failed create', function(done) { it('afterCreate should not be triggered on failed create', function (done) {
var old = User.dataSource.connector.create; var old = User.dataSource.connector.create;
User.dataSource.connector.create = function(modelName, id, cb) { User.dataSource.connector.create = function (modelName, id, cb) {
cb(new Error('error')); cb(new Error('error'));
} }
User.afterCreate = function() { User.afterCreate = function () {
throw new Error('shouldn\'t be called') throw new Error('shouldn\'t be called')
}; };
User.create(function (err, user) { User.create(function (err, user) {
@ -90,37 +90,37 @@ describe('hooks', function() {
}); });
}); });
describe('save', function() { describe('save', function () {
afterEach(removeHooks('Save')); afterEach(removeHooks('Save'));
it('should be triggered on create', function(done) { it('should be triggered on create', function (done) {
addHooks('Save', done); addHooks('Save', done);
User.create(); User.create();
}); });
it('should be triggered on new+save', function(done) { it('should be triggered on new+save', function (done) {
addHooks('Save', done); addHooks('Save', done);
(new User).save(); (new User).save();
}); });
it('should be triggered on updateAttributes', function(done) { it('should be triggered on updateAttributes', function (done) {
User.create(function(err, user) { User.create(function (err, user) {
addHooks('Save', done); addHooks('Save', done);
user.updateAttributes({name: 'Anatoliy'}); user.updateAttributes({name: 'Anatoliy'});
}); });
}); });
it('should be triggered on save', function(done) { it('should be triggered on save', function (done) {
User.create(function(err, user) { User.create(function (err, user) {
addHooks('Save', done); addHooks('Save', done);
user.name = 'Hamburger'; user.name = 'Hamburger';
user.save(); user.save();
}); });
}); });
it('should save full object', function(done) { it('should save full object', function (done) {
User.create(function(err, user) { User.create(function (err, user) {
User.beforeSave = function(next, data) { User.beforeSave = function (next, data) {
data.should.have.keys('id', 'name', 'email', data.should.have.keys('id', 'name', 'email',
'password', 'state') 'password', 'state')
done(); done();
@ -129,19 +129,19 @@ describe('hooks', function() {
}); });
}); });
it('should save actual modifications to database', function(done) { it('should save actual modifications to database', function (done) {
User.beforeSave = function(next, data) { User.beforeSave = function (next, data) {
data.password = 'hash'; data.password = 'hash';
next(); next();
}; };
User.destroyAll(function() { User.destroyAll(function () {
User.create({ User.create({
email: 'james.bond@example.com', email: 'james.bond@example.com',
password: '53cr3t' password: '53cr3t'
}, function() { }, function () {
User.findOne({ User.findOne({
where: {email: 'james.bond@example.com'} where: {email: 'james.bond@example.com'}
}, function(err, jb) { }, function (err, jb) {
jb.password.should.equal('hash'); jb.password.should.equal('hash');
done(); done();
}); });
@ -149,22 +149,22 @@ describe('hooks', function() {
}); });
}); });
it('should save actual modifications on updateAttributes', function(done) { it('should save actual modifications on updateAttributes', function (done) {
User.beforeSave = function(next, data) { User.beforeSave = function (next, data) {
data.password = 'hash'; data.password = 'hash';
next(); next();
}; };
User.destroyAll(function() { User.destroyAll(function () {
User.create({ User.create({
email: 'james.bond@example.com' email: 'james.bond@example.com'
}, function(err, u) { }, function (err, u) {
u.updateAttribute('password', 'new password', function(e, u) { u.updateAttribute('password', 'new password', function (e, u) {
should.not.exist(e); should.not.exist(e);
should.exist(u); should.exist(u);
u.password.should.equal('hash'); u.password.should.equal('hash');
User.findOne({ User.findOne({
where: {email: 'james.bond@example.com'} where: {email: 'james.bond@example.com'}
}, function(err, jb) { }, function (err, jb) {
jb.password.should.equal('hash'); jb.password.should.equal('hash');
done(); done();
}); });
@ -175,33 +175,33 @@ describe('hooks', function() {
}); });
describe('update', function() { describe('update', function () {
afterEach(removeHooks('Update')); afterEach(removeHooks('Update'));
it('should not be triggered on create', function() { it('should not be triggered on create', function () {
User.beforeUpdate = function(next) { User.beforeUpdate = function (next) {
should.fail('This should not be called'); should.fail('This should not be called');
next(); next();
}; };
User.create(); User.create();
}); });
it('should not be triggered on new+save', function() { it('should not be triggered on new+save', function () {
User.beforeUpdate = function(next) { User.beforeUpdate = function (next) {
should.fail('This should not be called'); should.fail('This should not be called');
next(); next();
}; };
(new User).save(); (new User).save();
}); });
it('should be triggered on updateAttributes', function(done) { it('should be triggered on updateAttributes', function (done) {
User.create(function (err, user) { User.create(function (err, user) {
addHooks('Update', done); addHooks('Update', done);
user.updateAttributes({name: 'Anatoliy'}); user.updateAttributes({name: 'Anatoliy'});
}); });
}); });
it('should be triggered on save', function(done) { it('should be triggered on save', function (done) {
User.create(function (err, user) { User.create(function (err, user) {
addHooks('Update', done); addHooks('Update', done);
user.name = 'Hamburger'; user.name = 'Hamburger';
@ -209,9 +209,9 @@ describe('hooks', function() {
}); });
}); });
it('should update limited set of fields', function(done) { it('should update limited set of fields', function (done) {
User.create(function (err, user) { User.create(function (err, user) {
User.beforeUpdate = function(next, data) { User.beforeUpdate = function (next, data) {
data.should.have.keys('name', 'email'); data.should.have.keys('name', 'email');
done(); done();
}; };
@ -219,35 +219,35 @@ describe('hooks', function() {
}); });
}); });
it('should not trigger after-hook on failed save', function(done) { it('should not trigger after-hook on failed save', function (done) {
User.afterUpdate = function() { User.afterUpdate = function () {
should.fail('afterUpdate shouldn\'t be called') should.fail('afterUpdate shouldn\'t be called')
}; };
User.create(function (err, user) { User.create(function (err, user) {
var save = User.dataSource.connector.save; var save = User.dataSource.connector.save;
User.dataSource.connector.save = function(modelName, id, cb) { User.dataSource.connector.save = function (modelName, id, cb) {
User.dataSource.connector.save = save; User.dataSource.connector.save = save;
cb(new Error('Error')); cb(new Error('Error'));
} }
user.save(function(err) { user.save(function (err) {
done(); done();
}); });
}); });
}); });
}); });
describe('destroy', function() { describe('destroy', function () {
afterEach(removeHooks('Destroy')); afterEach(removeHooks('Destroy'));
it('should be triggered on destroy', function(done) { it('should be triggered on destroy', function (done) {
var hook = 'not called'; var hook = 'not called';
User.beforeDestroy = function(next) { User.beforeDestroy = function (next) {
hook = 'called'; hook = 'called';
next(); next();
}; };
User.afterDestroy = function(next) { User.afterDestroy = function (next) {
hook.should.eql('called'); hook.should.eql('called');
next(); next();
}; };
@ -256,16 +256,16 @@ describe('hooks', function() {
}); });
}); });
it('should not trigger after-hook on failed destroy', function(done) { it('should not trigger after-hook on failed destroy', function (done) {
var destroy = User.dataSource.connector.destroy; var destroy = User.dataSource.connector.destroy;
User.dataSource.connector.destroy = function(modelName, id, cb) { User.dataSource.connector.destroy = function (modelName, id, cb) {
cb(new Error('error')); cb(new Error('error'));
} }
User.afterDestroy = function() { User.afterDestroy = function () {
should.fail('afterDestroy shouldn\'t be called') should.fail('afterDestroy shouldn\'t be called')
}; };
User.create(function (err, user) { User.create(function (err, user) {
user.destroy(function(err) { user.destroy(function (err) {
User.dataSource.connector.destroy = destroy; User.dataSource.connector.destroy = destroy;
done(); done();
}); });
@ -274,32 +274,64 @@ describe('hooks', function() {
}); });
describe('lifecycle', function() { describe('lifecycle', function () {
var life = [], user; var life = [], user;
before(function(done) { before(function (done) {
User.beforeSave = function(d){life.push('beforeSave'); d();}; User.beforeSave = function (d) {
User.beforeCreate = function(d){life.push('beforeCreate'); d();}; life.push('beforeSave');
User.beforeUpdate = function(d){life.push('beforeUpdate'); d();}; d();
User.beforeDestroy = function(d){life.push('beforeDestroy');d();}; };
User.beforeValidate = function(d){life.push('beforeValidate');d();}; User.beforeCreate = function (d) {
User.afterInitialize= function( ){life.push('afterInitialize'); }; life.push('beforeCreate');
User.afterSave = function(d){life.push('afterSave'); d();}; d();
User.afterCreate = function(d){life.push('afterCreate'); d();}; };
User.afterUpdate = function(d){life.push('afterUpdate'); d();}; User.beforeUpdate = function (d) {
User.afterDestroy = function(d){life.push('afterDestroy'); d();}; life.push('beforeUpdate');
User.afterValidate = function(d){life.push('afterValidate');d();}; d();
User.create(function(e, u) { };
User.beforeDestroy = function (d) {
life.push('beforeDestroy');
d();
};
User.beforeValidate = function (d) {
life.push('beforeValidate');
d();
};
User.afterInitialize = function () {
life.push('afterInitialize');
};
User.afterSave = function (d) {
life.push('afterSave');
d();
};
User.afterCreate = function (d) {
life.push('afterCreate');
d();
};
User.afterUpdate = function (d) {
life.push('afterUpdate');
d();
};
User.afterDestroy = function (d) {
life.push('afterDestroy');
d();
};
User.afterValidate = function (d) {
life.push('afterValidate');
d();
};
User.create(function (e, u) {
user = u; user = u;
life = []; life = [];
done(); done();
}); });
}); });
beforeEach(function() { beforeEach(function () {
life = []; life = [];
}); });
it('should describe create sequence', function(done) { it('should describe create sequence', function (done) {
User.create(function() { User.create(function () {
life.should.eql([ life.should.eql([
'afterInitialize', 'afterInitialize',
'beforeValidate', 'beforeValidate',
@ -313,9 +345,9 @@ describe('hooks', function() {
}); });
}); });
it('should describe new+save sequence', function(done) { it('should describe new+save sequence', function (done) {
var u = new User; var u = new User;
u.save(function() { u.save(function () {
life.should.eql([ life.should.eql([
'afterInitialize', 'afterInitialize',
'beforeValidate', 'beforeValidate',
@ -329,8 +361,8 @@ describe('hooks', function() {
}); });
}); });
it('should describe updateAttributes sequence', function(done) { it('should describe updateAttributes sequence', function (done) {
user.updateAttributes({name: 'Antony'}, function() { user.updateAttributes({name: 'Antony'}, function () {
life.should.eql([ life.should.eql([
'beforeValidate', 'beforeValidate',
'afterValidate', 'afterValidate',
@ -343,11 +375,11 @@ describe('hooks', function() {
}); });
}); });
it('should describe isValid sequence', function(done) { it('should describe isValid sequence', function (done) {
should.not.exist( should.not.exist(
user.constructor._validations, user.constructor._validations,
'Expected user to have no validations, but she have'); 'Expected user to have no validations, but she have');
user.isValid(function(valid) { user.isValid(function (valid) {
valid.should.be.true; valid.should.be.true;
life.should.eql([ life.should.eql([
'beforeValidate', 'beforeValidate',
@ -357,8 +389,8 @@ describe('hooks', function() {
}); });
}); });
it('should describe destroy sequence', function(done) { it('should describe destroy sequence', function (done) {
user.destroy(function() { user.destroy(function () {
life.should.eql([ life.should.eql([
'beforeDestroy', 'beforeDestroy',
'afterDestroy' 'afterDestroy'
@ -372,12 +404,12 @@ describe('hooks', function() {
function addHooks(name, done) { function addHooks(name, done) {
var called = false, random = String(Math.floor(Math.random() * 1000)); var called = false, random = String(Math.floor(Math.random() * 1000));
User['before' + name] = function(next, data) { User['before' + name] = function (next, data) {
called = true; called = true;
data.email = random; data.email = random;
next(); next();
}; };
User['after' + name] = function(next) { User['after' + name] = function (next) {
(new Boolean(called)).should.equal(true); (new Boolean(called)).should.equal(true);
this.email.should.equal(random); this.email.should.equal(random);
done(); done();
@ -385,7 +417,7 @@ function addHooks(name, done) {
} }
function removeHooks(name) { function removeHooks(name) {
return function() { return function () {
User['after' + name] = null; User['after' + name] = null;
User['before' + name] = null; User['before' + name] = null;
}; };

View File

@ -4,14 +4,14 @@ var should = require('./init.js');
var db, User, Post, Passport, City, Street, Building; var db, User, Post, Passport, City, Street, Building;
var nbSchemaRequests = 0; var nbSchemaRequests = 0;
describe('include', function() { describe('include', function () {
before(setup); before(setup);
it('should fetch belongsTo relation', function(done) { it('should fetch belongsTo relation', function (done) {
Passport.all({include: 'owner'}, function (err, passports) { Passport.all({include: 'owner'}, function (err, passports) {
passports.length.should.be.ok; passports.length.should.be.ok;
passports.forEach(function(p) { passports.forEach(function (p) {
p.__cachedRelations.should.have.property('owner'); p.__cachedRelations.should.have.property('owner');
var owner = p.__cachedRelations.owner; var owner = p.__cachedRelations.owner;
if (!p.ownerId) { if (!p.ownerId) {
@ -25,14 +25,14 @@ describe('include', function() {
}); });
}); });
it('should fetch hasMany relation', function(done) { it('should fetch hasMany relation', function (done) {
User.all({include: 'posts'}, function (err, users) { User.all({include: 'posts'}, function (err, users) {
should.not.exist(err); should.not.exist(err);
should.exist(users); should.exist(users);
users.length.should.be.ok; users.length.should.be.ok;
users.forEach(function(u) { users.forEach(function (u) {
u.__cachedRelations.should.have.property('posts'); u.__cachedRelations.should.have.property('posts');
u.__cachedRelations.posts.forEach(function(p) { u.__cachedRelations.posts.forEach(function (p) {
p.userId.should.equal(u.id); p.userId.should.equal(u.id);
}); });
}); });
@ -40,12 +40,12 @@ describe('include', function() {
}); });
}); });
it('should fetch Passport - Owner - Posts', function(done) { it('should fetch Passport - Owner - Posts', function (done) {
Passport.all({include: {owner: 'posts'}}, function(err, passports) { Passport.all({include: {owner: 'posts'}}, function (err, passports) {
should.not.exist(err); should.not.exist(err);
should.exist(passports); should.exist(passports);
passports.length.should.be.ok; passports.length.should.be.ok;
passports.forEach(function(p) { passports.forEach(function (p) {
p.__cachedRelations.should.have.property('owner'); p.__cachedRelations.should.have.property('owner');
var user = p.__cachedRelations.owner; var user = p.__cachedRelations.owner;
if (!p.ownerId) { if (!p.ownerId) {
@ -54,7 +54,7 @@ describe('include', function() {
should.exist(user); should.exist(user);
user.id.should.equal(p.ownerId); user.id.should.equal(p.ownerId);
user.__cachedRelations.should.have.property('posts'); user.__cachedRelations.should.have.property('posts');
user.__cachedRelations.posts.forEach(function(pp) { user.__cachedRelations.posts.forEach(function (pp) {
pp.userId.should.equal(user.id); pp.userId.should.equal(user.id);
}); });
} }
@ -63,14 +63,14 @@ describe('include', function() {
}); });
}); });
it('should fetch Passports - User - Posts - User', function(done) { it('should fetch Passports - User - Posts - User', function (done) {
Passport.all({ Passport.all({
include: {owner: {posts: 'author'}} include: {owner: {posts: 'author'}}
}, function(err, passports) { }, function (err, passports) {
should.not.exist(err); should.not.exist(err);
should.exist(passports); should.exist(passports);
passports.length.should.be.ok; passports.length.should.be.ok;
passports.forEach(function(p) { passports.forEach(function (p) {
p.__cachedRelations.should.have.property('owner'); p.__cachedRelations.should.have.property('owner');
var user = p.__cachedRelations.owner; var user = p.__cachedRelations.owner;
if (!p.ownerId) { if (!p.ownerId) {
@ -79,7 +79,7 @@ describe('include', function() {
should.exist(user); should.exist(user);
user.id.should.equal(p.ownerId); user.id.should.equal(p.ownerId);
user.__cachedRelations.should.have.property('posts'); user.__cachedRelations.should.have.property('posts');
user.__cachedRelations.posts.forEach(function(pp) { user.__cachedRelations.posts.forEach(function (pp) {
pp.userId.should.equal(user.id); pp.userId.should.equal(user.id);
pp.__cachedRelations.should.have.property('author'); pp.__cachedRelations.should.have.property('author');
var author = pp.__cachedRelations.author; var author = pp.__cachedRelations.author;
@ -91,18 +91,18 @@ describe('include', function() {
}); });
}); });
it('should fetch User - Posts AND Passports', function(done) { it('should fetch User - Posts AND Passports', function (done) {
User.all({include: ['posts', 'passports']}, function(err, users) { User.all({include: ['posts', 'passports']}, function (err, users) {
should.not.exist(err); should.not.exist(err);
should.exist(users); should.exist(users);
users.length.should.be.ok; users.length.should.be.ok;
users.forEach(function(user) { users.forEach(function (user) {
user.__cachedRelations.should.have.property('posts'); user.__cachedRelations.should.have.property('posts');
user.__cachedRelations.should.have.property('passports'); user.__cachedRelations.should.have.property('passports');
user.__cachedRelations.posts.forEach(function(p) { user.__cachedRelations.posts.forEach(function (p) {
p.userId.should.equal(user.id); p.userId.should.equal(user.id);
}); });
user.__cachedRelations.passports.forEach(function(pp) { user.__cachedRelations.passports.forEach(function (pp) {
pp.ownerId.should.equal(user.id); pp.ownerId.should.equal(user.id);
}); });
}); });
@ -133,7 +133,7 @@ function setup(done) {
User.hasMany('posts', {foreignKey: 'userId'}); User.hasMany('posts', {foreignKey: 'userId'});
Post.belongsTo('author', {model: User, foreignKey: 'userId'}); Post.belongsTo('author', {model: User, foreignKey: 'userId'});
db.automigrate(function() { db.automigrate(function () {
var createdUsers = []; var createdUsers = [];
var createdPassports = []; var createdPassports = [];
var createdPosts = []; var createdPosts = [];
@ -148,7 +148,7 @@ function setup(done) {
{name: 'User D', age: 24}, {name: 'User D', age: 24},
{name: 'User E', age: 25} {name: 'User E', age: 25}
], ],
function(items) { function (items) {
createdUsers = items; createdUsers = items;
createPassports(); createPassports();
} }
@ -163,7 +163,7 @@ function setup(done) {
{number: '2', ownerId: createdUsers[1].id}, {number: '2', ownerId: createdUsers[1].id},
{number: '3'} {number: '3'}
], ],
function(items) { function (items) {
createdPassports = items; createdPassports = items;
createPosts(); createPosts();
} }
@ -180,7 +180,7 @@ function setup(done) {
{title: 'Post D', userId: createdUsers[1].id}, {title: 'Post D', userId: createdUsers[1].id},
{title: 'Post E'} {title: 'Post E'}
], ],
function(items) { function (items) {
createdPosts = items; createdPosts = items;
done(); done();
} }
@ -197,6 +197,7 @@ function clearAndCreate(model, data, callback) {
}); });
var itemIndex = 0; var itemIndex = 0;
function nextItem(err, lastItem) { function nextItem(err, lastItem) {
if (lastItem !== null) { if (lastItem !== null) {
createdItems.push(lastItem); createdItems.push(lastItem);

View File

@ -1,7 +1,7 @@
module.exports = require('should'); module.exports = require('should');
/* /*
if (!process.env.TRAVIS) { if (!process.env.TRAVIS) {
if (typeof __cov === 'undefined') { if (typeof __cov === 'undefined') {
process.on('exit', function () { process.on('exit', function () {
require('semicov').report(); require('semicov').report();
@ -9,13 +9,13 @@ if (!process.env.TRAVIS) {
} }
require('semicov').init('lib'); require('semicov').init('lib');
} }
*/ */
var Schema = require('../').Schema; var Schema = require('../').Schema;
if (!('getSchema' in global)) { if (!('getSchema' in global)) {
global.getSchema = function() { global.getSchema = function () {
return new Schema('memory'); return new Schema('memory');
}; };
} }

View File

@ -3,9 +3,9 @@ var ModelBuilder = require('../lib/model-builder').ModelBuilder;
var introspectType = require('../lib/introspection')(ModelBuilder); var introspectType = require('../lib/introspection')(ModelBuilder);
var traverse = require('traverse'); var traverse = require('traverse');
describe('Introspection of model definitions from JSON', function() { describe('Introspection of model definitions from JSON', function () {
it('should handle simple types', function() { it('should handle simple types', function () {
assert.equal(introspectType('123'), 'string'); assert.equal(introspectType('123'), 'string');
assert.equal(introspectType(true), 'boolean'); assert.equal(introspectType(true), 'boolean');
assert.equal(introspectType(false), 'boolean'); assert.equal(introspectType(false), 'boolean');
@ -13,7 +13,7 @@ describe('Introspection of model definitions from JSON', function() {
assert.equal(introspectType(new Date()), 'date'); assert.equal(introspectType(new Date()), 'date');
}); });
it('should handle array types', function() { it('should handle array types', function () {
var type = introspectType(['123']); var type = introspectType(['123']);
assert.deepEqual(type, ['string'], 'type should be ["string"]'); assert.deepEqual(type, ['string'], 'type should be ["string"]');
type = introspectType([1]); type = introspectType([1]);
@ -28,12 +28,12 @@ describe('Introspection of model definitions from JSON', function() {
assert.equal(type, 'array'); assert.equal(type, 'array');
}); });
it('should return Any for null or undefined', function() { it('should return Any for null or undefined', function () {
assert.equal(introspectType(null), ModelBuilder.Any); assert.equal(introspectType(null), ModelBuilder.Any);
assert.equal(introspectType(undefined), ModelBuilder.Any); assert.equal(introspectType(undefined), ModelBuilder.Any);
}); });
it('should return a schema for object', function() { it('should return a schema for object', function () {
var json = {a: 'str', b: 0, c: true}; var json = {a: 'str', b: 0, c: true};
var type = introspectType(json); var type = introspectType(json);
assert.equal(type.a, 'string'); assert.equal(type.a, 'string');
@ -41,7 +41,7 @@ describe('Introspection of model definitions from JSON', function() {
assert.equal(type.c, 'boolean'); assert.equal(type.c, 'boolean');
}); });
it('should handle nesting objects', function() { it('should handle nesting objects', function () {
var json = {a: 'str', b: 0, c: true, d: {x: 10, y: 5}}; var json = {a: 'str', b: 0, c: true, d: {x: 10, y: 5}};
var type = introspectType(json); var type = introspectType(json);
assert.equal(type.a, 'string'); assert.equal(type.a, 'string');
@ -51,7 +51,7 @@ describe('Introspection of model definitions from JSON', function() {
assert.equal(type.d.y, 'number'); assert.equal(type.d.y, 'number');
}); });
it('should handle nesting arrays', function() { it('should handle nesting arrays', function () {
var json = {a: 'str', b: 0, c: true, d: [1, 2]}; var json = {a: 'str', b: 0, c: true, d: [1, 2]};
var type = introspectType(json); var type = introspectType(json);
assert.equal(type.a, 'string'); assert.equal(type.a, 'string');
@ -60,7 +60,7 @@ describe('Introspection of model definitions from JSON', function() {
assert.deepEqual(type.d, ['number']); assert.deepEqual(type.d, ['number']);
}); });
it('should build a model from the introspected schema', function(done) { it('should build a model from the introspected schema', function (done) {
var json = { var json = {
name: 'Joe', name: 'Joe',

View File

@ -4,10 +4,10 @@ var should = require('./init.js');
var Schema = require('../').Schema; var Schema = require('../').Schema;
var ModelBuilder = require('../').ModelBuilder; var ModelBuilder = require('../').ModelBuilder;
describe('JSON property', function() { describe('JSON property', function () {
var dataSource, Model; var dataSource, Model;
it('should be defined', function() { it('should be defined', function () {
dataSource = getSchema(); dataSource = getSchema();
Model = dataSource.define('Model', {propertyName: ModelBuilder.JSON}); Model = dataSource.define('Model', {propertyName: ModelBuilder.JSON});
var m = new Model; var m = new Model;
@ -15,7 +15,7 @@ describe('JSON property', function() {
should.not.exist(m.propertyName); should.not.exist(m.propertyName);
}); });
it('should accept JSON in constructor and return object', function() { it('should accept JSON in constructor and return object', function () {
var m = new Model({ var m = new Model({
propertyName: '{"foo": "bar"}' propertyName: '{"foo": "bar"}'
}); });
@ -23,14 +23,14 @@ describe('JSON property', function() {
m.propertyName.foo.should.equal('bar'); m.propertyName.foo.should.equal('bar');
}); });
it('should accept object in setter and return object', function() { it('should accept object in setter and return object', function () {
var m = new Model; var m = new Model;
m.propertyName = {"foo": "bar"}; m.propertyName = {"foo": "bar"};
m.propertyName.should.be.an.Object; m.propertyName.should.be.an.Object;
m.propertyName.foo.should.equal('bar'); m.propertyName.foo.should.equal('bar');
}); });
it('should accept string in setter and return string', function() { it('should accept string in setter and return string', function () {
var m = new Model; var m = new Model;
m.propertyName = '{"foo": "bar"}'; m.propertyName = '{"foo": "bar"}';
m.propertyName.should.be.a.String; m.propertyName.should.be.a.String;

View File

@ -3,7 +3,7 @@ var should = require('./init.js');
var loopbackData = require('../'); var loopbackData = require('../');
describe('loopback-datasource-juggler', function() { describe('loopback-datasource-juggler', function () {
it('should expose version', function () { it('should expose version', function () {
loopbackData.version.should.equal(require('../package.json').version); loopbackData.version.should.equal(require('../package.json').version);
}); });

View File

@ -62,7 +62,7 @@ describe('ModelBuilder define model', function () {
try { try {
var user = new User({name: 'Joe', age: 20}); var user = new User({name: 'Joe', age: 20});
assert(false, 'The code should have thrown an error'); assert(false, 'The code should have thrown an error');
} catch(e) { } catch (e) {
assert(true, 'The code is expected to throw an error'); assert(true, 'The code is expected to throw an error');
} }
done(null, User); done(null, User);
@ -98,7 +98,6 @@ describe('ModelBuilder define model', function () {
done(null, User); done(null, User);
}); });
it('should be able to define nesting models', function (done) { it('should be able to define nesting models', function (done) {
var modelBuilder = new ModelBuilder(); var modelBuilder = new ModelBuilder();
@ -116,10 +115,12 @@ describe('ModelBuilder define model', function () {
zipCode: String, zipCode: String,
country: String country: String
}, },
emails: [{ emails: [
{
label: String, label: String,
email: String email: String
}], }
],
friends: [String] friends: [String]
}); });
@ -134,7 +135,9 @@ describe('ModelBuilder define model', function () {
var user = new User({ var user = new User({
name: 'Joe', age: 20, name: 'Joe', age: 20,
address: {street: '123 Main St', 'city': 'San Jose', state: 'CA'}, address: {street: '123 Main St', 'city': 'San Jose', state: 'CA'},
emails: [{label: 'work', email: 'xyz@sample.com'}], emails: [
{label: 'work', email: 'xyz@sample.com'}
],
friends: ['Mary', 'John'] friends: ['Mary', 'John']
}); });
@ -189,10 +192,8 @@ describe('ModelBuilder define model', function () {
done(null, User); done(null, User);
}); });
}); });
describe('DataSource define model', function () { describe('DataSource define model', function () {
it('should be able to define plain models', function () { it('should be able to define plain models', function () {
var ds = new DataSource('memory'); var ds = new DataSource('memory');
@ -323,7 +324,7 @@ describe('DataSource define model', function () {
try { try {
var user = new User({name: 'Joe', age: 20}); var user = new User({name: 'Joe', age: 20});
assert(false, 'The code should have thrown an error'); assert(false, 'The code should have thrown an error');
} catch(e) { } catch (e) {
assert(true, 'The code is expected to throw an error'); assert(true, 'The code is expected to throw an error');
} }
done(null, User); done(null, User);
@ -342,7 +343,7 @@ describe('DataSource define model', function () {
user.should.have.property('age', 20); user.should.have.property('age', 20);
user.should.not.have.property('bio'); user.should.not.have.property('bio');
User.findById(user.id, function(err, user) { User.findById(user.id, function (err, user) {
user.should.be.a('object').and.have.property('name', 'Joe'); user.should.be.a('object').and.have.property('name', 'Joe');
user.should.have.property('name', 'Joe'); user.should.have.property('name', 'Joe');
user.should.have.property('age', 20); user.should.have.property('age', 20);
@ -395,21 +396,20 @@ describe('DataSource define model', function () {
try { try {
var user = new User({name: 'Joe', age: 20}); var user = new User({name: 'Joe', age: 20});
assert(false, 'The code should have thrown an error'); assert(false, 'The code should have thrown an error');
} catch(e) { } catch (e) {
assert(true, 'The code is expected to throw an error'); assert(true, 'The code is expected to throw an error');
} }
done(null, User); done(null, User);
}); });
it('should change the property value for save if strict=false', function (done) { it('should change the property value for save if strict=false', function (done) {
var ds = new DataSource('memory');// define models var ds = new DataSource('memory');// define models
var Post = ds.define('Post'); var Post = ds.define('Post');
Post.create({price: 900}, function(err, post) { Post.create({price: 900}, function (err, post) {
assert.equal(post.price, 900); assert.equal(post.price, 900);
post.price = 1000; post.price = 1000;
post.save(function(err, result) { post.save(function (err, result) {
assert.equal(1000, result.price); assert.equal(1000, result.price);
done(err, result); done(err, result);
}); });
@ -424,8 +424,10 @@ describe('Load models with base', function () {
var User = ds.define('User', {name: String}); var User = ds.define('User', {name: String});
User.staticMethod = function staticMethod() {}; User.staticMethod = function staticMethod() {
User.prototype.instanceMethod = function instanceMethod() {}; };
User.prototype.instanceMethod = function instanceMethod() {
};
var Customer = ds.define('Customer', {vip: Boolean}, {base: 'User'}); var Customer = ds.define('Customer', {vip: Boolean}, {base: 'User'});
@ -433,10 +435,9 @@ describe('Load models with base', function () {
assert(Customer.staticMethod === User.staticMethod); assert(Customer.staticMethod === User.staticMethod);
assert(Customer.prototype.instanceMethod === User.prototype.instanceMethod); assert(Customer.prototype.instanceMethod === User.prototype.instanceMethod);
try { try {
var Customer1 = ds.define('Customer1', {vip: Boolean}, {base: 'User1'}); var Customer1 = ds.define('Customer1', {vip: Boolean}, {base: 'User1'});
} catch(e) { } catch (e) {
assert(e); assert(e);
} }
@ -444,45 +445,45 @@ describe('Load models with base', function () {
}); });
}); });
describe('DataSource constructor', function() { describe('DataSource constructor', function () {
// Mocked require // Mocked require
var loader = function(name) { var loader = function (name) {
return { return {
name: name name: name
} }
}; };
it('should resolve connector by path', function() { it('should resolve connector by path', function () {
var connector = DataSource._resolveConnector(__dirname + '/../lib/connectors/memory'); var connector = DataSource._resolveConnector(__dirname + '/../lib/connectors/memory');
assert(connector.connector); assert(connector.connector);
}); });
it('should resolve connector by internal name', function() { it('should resolve connector by internal name', function () {
var connector = DataSource._resolveConnector('memory'); var connector = DataSource._resolveConnector('memory');
assert(connector.connector); assert(connector.connector);
}); });
it('should try to resolve connector by module name starts with loopback-connector-', function() { it('should try to resolve connector by module name starts with loopback-connector-', function () {
var connector = DataSource._resolveConnector('loopback-connector-xyz', loader); var connector = DataSource._resolveConnector('loopback-connector-xyz', loader);
assert(connector.connector); assert(connector.connector);
}); });
it('should try to resolve connector by short module name', function() { it('should try to resolve connector by short module name', function () {
var connector = DataSource._resolveConnector('xyz', loader); var connector = DataSource._resolveConnector('xyz', loader);
assert(connector.connector); assert(connector.connector);
}); });
it('should try to resolve connector by full module name', function() { it('should try to resolve connector by full module name', function () {
var connector = DataSource._resolveConnector('loopback-xyz', loader); var connector = DataSource._resolveConnector('loopback-xyz', loader);
assert(connector.connector); assert(connector.connector);
}); });
it('should fail to resolve connector by module name starts with loopback-connector-', function() { it('should fail to resolve connector by module name starts with loopback-connector-', function () {
var connector = DataSource._resolveConnector('loopback-connector-xyz'); var connector = DataSource._resolveConnector('loopback-connector-xyz');
assert(!connector.connector); assert(!connector.connector);
assert(connector.error.indexOf('loopback-connector-xyz') !== -1); assert(connector.error.indexOf('loopback-connector-xyz') !== -1);
}); });
it('should fail to resolve connector by short module name', function() { it('should fail to resolve connector by short module name', function () {
var connector = DataSource._resolveConnector('xyz'); var connector = DataSource._resolveConnector('xyz');
assert(!connector.connector); assert(!connector.connector);
assert(connector.error.indexOf('loopback-connector-xyz') !== -1); assert(connector.error.indexOf('loopback-connector-xyz') !== -1);
}); });
it('should fail to resolve connector by full module name', function() { it('should fail to resolve connector by full module name', function () {
var connector = DataSource._resolveConnector('loopback-xyz'); var connector = DataSource._resolveConnector('loopback-xyz');
assert(!connector.connector); assert(!connector.connector);
assert(connector.error.indexOf('loopback-connector-loopback-xyz') !== -1); assert(connector.error.indexOf('loopback-connector-loopback-xyz') !== -1);
@ -627,7 +628,6 @@ describe('Load models with relations', function () {
done(); done();
}); });
}); });
describe('DataAccessObject', function () { describe('DataAccessObject', function () {
@ -741,7 +741,6 @@ describe('Load models from json', function () {
var path = require('path'), var path = require('path'),
fs = require('fs'); fs = require('fs');
/** /**
* Load LDL schemas from a json doc * Load LDL schemas from a json doc
* @param schemaFile The dataSource json file * @param schemaFile The dataSource json file
@ -803,8 +802,8 @@ describe('Load models from json', function () {
// The properties are defined at prototype level // The properties are defined at prototype level
assert.equal(Object.keys(customer).length, 0); assert.equal(Object.keys(customer).length, 0);
var count = 0; var count = 0;
for(var p in customer) { for (var p in customer) {
if(typeof customer[p] !== 'function') { if (typeof customer[p] !== 'function') {
count++; count++;
} }
} }
@ -831,7 +830,7 @@ describe('Load models from json', function () {
relations: { relations: {
posts: { posts: {
type: 'hasMany', type: 'hasMany',
model:'Post' model: 'Post'
} }
} }
}); });
@ -850,7 +849,7 @@ describe('Load models from json', function () {
relations: { relations: {
orders: { orders: {
type: 'hasMany', type: 'hasMany',
model:'Order' model: 'Order'
} }
} }
} }
@ -868,7 +867,7 @@ describe('Load models from json', function () {
relations: { relations: {
posts: { posts: {
type: 'hasMany', type: 'hasMany',
model:'Post' model: 'Post'
} }
}, },
strict: false strict: false
@ -891,11 +890,11 @@ describe('Load models from json', function () {
relations: { relations: {
posts: { posts: {
type: 'hasMany', type: 'hasMany',
model:'Post' model: 'Post'
}, },
orders: { orders: {
type: 'hasMany', type: 'hasMany',
model:'Order' model: 'Order'
} }
}, },
strict: false strict: false
@ -905,31 +904,30 @@ describe('Load models from json', function () {
}); });
}); });
describe('DataSource constructor', function(){ describe('DataSource constructor', function () {
it('Takes url as the settings', function() { it('Takes url as the settings', function () {
var ds = new DataSource('memory://localhost/mydb?x=1'); var ds = new DataSource('memory://localhost/mydb?x=1');
assert.equal(ds.connector.name, 'memory'); assert.equal(ds.connector.name, 'memory');
}); });
it('Takes connector name', function() { it('Takes connector name', function () {
var ds = new DataSource('memory'); var ds = new DataSource('memory');
assert.equal(ds.connector.name, 'memory'); assert.equal(ds.connector.name, 'memory');
}); });
it('Takes settings object', function() { it('Takes settings object', function () {
var ds = new DataSource({connector: 'memory'}); var ds = new DataSource({connector: 'memory'});
assert.equal(ds.connector.name, 'memory'); assert.equal(ds.connector.name, 'memory');
}); });
it('Takes settings object and name', function() { it('Takes settings object and name', function () {
var ds = new DataSource('x', {connector: 'memory'}); var ds = new DataSource('x', {connector: 'memory'});
assert.equal(ds.connector.name, 'memory'); assert.equal(ds.connector.name, 'memory');
}); });
}); });
describe('Injected methods from connectors', function () {
describe('Injected methods from connectors', function(){ it('are not shared across models for remote methods', function () {
it('are not shared across models for remote methods', function() {
var ds = new DataSource('memory'); var ds = new DataSource('memory');
var M1 = ds.createModel('M1'); var M1 = ds.createModel('M1');
var M2 = ds.createModel('M2'); var M2 = ds.createModel('M2');
@ -942,7 +940,7 @@ describe('Injected methods from connectors', function(){
assert.equal(M2.create.shared, true, 'M2.create should stay remotable'); assert.equal(M2.create.shared, true, 'M2.create should stay remotable');
}); });
it('are not shared across models for non-remote methods', function() { it('are not shared across models for non-remote methods', function () {
var ds = new DataSource('memory'); var ds = new DataSource('memory');
var M1 = ds.createModel('M1'); var M1 = ds.createModel('M1');
var M2 = ds.createModel('M2'); var M2 = ds.createModel('M2');
@ -965,9 +963,8 @@ describe('Injected methods from connectors', function(){
}); });
describe('ModelBuilder options.models', function () {
describe('ModelBuilder options.models', function(){ it('should inject model classes from models', function () {
it('should inject model classes from models', function() {
var builder = new ModelBuilder(); var builder = new ModelBuilder();
var M1 = builder.define('M1'); var M1 = builder.define('M1');
var M2 = builder.define('M2', {}, {models: { var M2 = builder.define('M2', {}, {models: {
@ -977,7 +974,7 @@ describe('ModelBuilder options.models', function(){
assert.equal(M2.M1, M1, 'M1 should be injected to M2'); assert.equal(M2.M1, M1, 'M1 should be injected to M2');
}); });
it('should inject model classes by name in the models', function() { it('should inject model classes by name in the models', function () {
var builder = new ModelBuilder(); var builder = new ModelBuilder();
var M1 = builder.define('M1'); var M1 = builder.define('M1');
var M2 = builder.define('M2', {}, {models: { var M2 = builder.define('M2', {}, {models: {
@ -988,7 +985,7 @@ describe('ModelBuilder options.models', function(){
}); });
it('should inject model classes by name in the models before the class is defined', it('should inject model classes by name in the models before the class is defined',
function() { function () {
var builder = new ModelBuilder(); var builder = new ModelBuilder();
var M2 = builder.define('M2', {}, {models: { var M2 = builder.define('M2', {}, {models: {
'M1': 'M1' 'M1': 'M1'

View File

@ -4,9 +4,9 @@ var should = require('./init.js');
var db, Person; var db, Person;
var ValidationError = require('..').ValidationError; var ValidationError = require('..').ValidationError;
describe('manipulation', function() { describe('manipulation', function () {
before(function(done) { before(function (done) {
db = getSchema(); db = getSchema();
Person = db.define('Person', { Person = db.define('Person', {
@ -22,18 +22,18 @@ describe('manipulation', function() {
}); });
describe('create', function() { describe('create', function () {
before(function(done) { before(function (done) {
Person.destroyAll(done); Person.destroyAll(done);
}); });
it('should create instance', function(done) { it('should create instance', function (done) {
Person.create({name: 'Anatoliy'}, function(err, p) { Person.create({name: 'Anatoliy'}, function (err, p) {
p.name.should.equal('Anatoliy'); p.name.should.equal('Anatoliy');
should.not.exist(err); should.not.exist(err);
should.exist(p); should.exist(p);
Person.findById(p.id, function(err, person) { Person.findById(p.id, function (err, person) {
person.id.should.equal(p.id); person.id.should.equal(p.id);
person.name.should.equal('Anatoliy'); person.name.should.equal('Anatoliy');
done(); done();
@ -41,8 +41,8 @@ describe('manipulation', function() {
}); });
}); });
it('should return instance of object', function(done) { it('should return instance of object', function (done) {
var person = Person.create(function(err, p) { var person = Person.create(function (err, p) {
p.id.should.eql(person.id); p.id.should.eql(person.id);
done(); done();
}); });
@ -51,8 +51,8 @@ describe('manipulation', function() {
should.not.exist(person.id); should.not.exist(person.id);
}); });
it('should work when called without callback', function(done) { it('should work when called without callback', function (done) {
Person.afterCreate = function(next) { Person.afterCreate = function (next) {
this.should.be.an.instanceOf(Person); this.should.be.an.instanceOf(Person);
this.name.should.equal('Nickolay'); this.name.should.equal('Nickolay');
should.exist(this.id); should.exist(this.id);
@ -63,12 +63,12 @@ describe('manipulation', function() {
Person.create({name: 'Nickolay'}); Person.create({name: 'Nickolay'});
}); });
it('should create instance with blank data', function(done) { it('should create instance with blank data', function (done) {
Person.create(function(err, p) { Person.create(function (err, p) {
should.not.exist(err); should.not.exist(err);
should.exist(p); should.exist(p);
should.not.exists(p.name); should.not.exists(p.name);
Person.findById(p.id, function(err, person) { Person.findById(p.id, function (err, person) {
person.id.should.equal(p.id); person.id.should.equal(p.id);
should.not.exists(person.name); should.not.exists(person.name);
done(); done();
@ -76,8 +76,8 @@ describe('manipulation', function() {
}); });
}); });
it('should work when called with no data and callback', function(done) { it('should work when called with no data and callback', function (done) {
Person.afterCreate = function(next) { Person.afterCreate = function (next) {
this.should.be.an.instanceOf(Person); this.should.be.an.instanceOf(Person);
should.not.exist(this.name); should.not.exist(this.name);
should.exist(this.id); should.exist(this.id);
@ -88,16 +88,20 @@ describe('manipulation', function() {
Person.create(); Person.create();
}); });
it('should create batch of objects', function(done) { it('should create batch of objects', function (done) {
var batch = [{name: 'Shaltay'}, {name: 'Boltay'}, {}]; var batch = [
Person.create(batch, function(e, ps) { {name: 'Shaltay'},
{name: 'Boltay'},
{}
];
Person.create(batch,function (e, ps) {
should.not.exist(e); should.not.exist(e);
should.exist(ps); should.exist(ps);
ps.should.be.instanceOf(Array); ps.should.be.instanceOf(Array);
ps.should.have.lengthOf(batch.length); ps.should.have.lengthOf(batch.length);
Person.validatesPresenceOf('name'); Person.validatesPresenceOf('name');
Person.create(batch, function(errors, persons) { Person.create(batch,function (errors, persons) {
delete Person._validations; delete Person._validations;
should.exist(errors); should.exist(errors);
errors.should.have.lengthOf(batch.length); errors.should.have.lengthOf(batch.length);
@ -114,26 +118,26 @@ describe('manipulation', function() {
}); });
}); });
describe('save', function() { describe('save', function () {
it('should save new object', function(done) { it('should save new object', function (done) {
var p = new Person; var p = new Person;
p.save(function(err) { p.save(function (err) {
should.not.exist(err); should.not.exist(err);
should.exist(p.id); should.exist(p.id);
done(); done();
}); });
}); });
it('should save existing object', function(done) { it('should save existing object', function (done) {
Person.findOne(function(err, p) { Person.findOne(function (err, p) {
should.not.exist(err); should.not.exist(err);
p.name = 'Hans'; p.name = 'Hans';
p.propertyChanged('name').should.be.true; p.propertyChanged('name').should.be.true;
p.save(function(err) { p.save(function (err) {
should.not.exist(err); should.not.exist(err);
p.propertyChanged('name').should.be.false; p.propertyChanged('name').should.be.false;
Person.findOne(function(err, p) { Person.findOne(function (err, p) {
should.not.exist(err); should.not.exist(err);
p.name.should.equal('Hans'); p.name.should.equal('Hans');
p.propertyChanged('name').should.be.false; p.propertyChanged('name').should.be.false;
@ -143,18 +147,18 @@ describe('manipulation', function() {
}); });
}); });
it('should save invalid object (skipping validation)', function(done) { it('should save invalid object (skipping validation)', function (done) {
Person.findOne(function(err, p) { Person.findOne(function (err, p) {
should.not.exist(err); should.not.exist(err);
p.isValid = function(done) { p.isValid = function (done) {
process.nextTick(done); process.nextTick(done);
return false; return false;
}; };
p.name = 'Nana'; p.name = 'Nana';
p.save(function(err) { p.save(function (err) {
should.exist(err); should.exist(err);
p.propertyChanged('name').should.be.true; p.propertyChanged('name').should.be.true;
p.save({validate: false}, function(err) { p.save({validate: false}, function (err) {
should.not.exist(err); should.not.exist(err);
p.propertyChanged('name').should.be.false; p.propertyChanged('name').should.be.false;
done(); done();
@ -163,14 +167,14 @@ describe('manipulation', function() {
}); });
}); });
it('should save throw error on validation', function() { it('should save throw error on validation', function () {
Person.findOne(function(err, p) { Person.findOne(function (err, p) {
should.not.exist(err); should.not.exist(err);
p.isValid = function(cb) { p.isValid = function (cb) {
cb(false); cb(false);
return false; return false;
}; };
(function() { (function () {
p.save({ p.save({
'throws': true 'throws': true
}); });
@ -180,19 +184,19 @@ describe('manipulation', function() {
}); });
describe('updateAttributes', function() { describe('updateAttributes', function () {
var person; var person;
before(function(done) { before(function (done) {
Person.destroyAll(function() { Person.destroyAll(function () {
person = Person.create(done); person = Person.create(done);
}); });
}); });
it('should update one attribute', function(done) { it('should update one attribute', function (done) {
person.updateAttribute('name', 'Paul Graham', function(err, p) { person.updateAttribute('name', 'Paul Graham', function (err, p) {
should.not.exist(err); should.not.exist(err);
Person.all(function(e, ps) { Person.all(function (e, ps) {
should.not.exist(err); should.not.exist(err);
ps.should.have.lengthOf(1); ps.should.have.lengthOf(1);
ps.pop().name.should.equal('Paul Graham'); ps.pop().name.should.equal('Paul Graham');
@ -202,13 +206,13 @@ describe('manipulation', function() {
}); });
}); });
describe('destroy', function() { describe('destroy', function () {
it('should destroy record', function(done) { it('should destroy record', function (done) {
Person.create(function(err, p){ Person.create(function (err, p) {
p.destroy(function(err) { p.destroy(function (err) {
should.not.exist(err); should.not.exist(err);
Person.exists(p.id, function(err, ex) { Person.exists(p.id, function (err, ex) {
ex.should.not.be.ok; ex.should.not.be.ok;
done(); done();
}); });
@ -233,8 +237,8 @@ describe('manipulation', function() {
it('should destroy filtered set of records'); it('should destroy filtered set of records');
}); });
describe('initialize', function() { describe('initialize', function () {
it('should initialize object properly', function() { it('should initialize object properly', function () {
var hw = 'Hello word', var hw = 'Hello word',
now = Date.now(), now = Date.now(),
person = new Person({name: hw}); person = new Person({name: hw});

View File

@ -29,7 +29,6 @@ describe('ModelDefinition class', function () {
assert.equal(User.properties.joinedAt.type, Date); assert.equal(User.properties.joinedAt.type, Date);
assert.equal(User.properties.age.type, Number); assert.equal(User.properties.age.type, Number);
var json = User.toJSON(); var json = User.toJSON();
assert.equal(json.name, "User"); assert.equal(json.name, "User");
assert.equal(json.properties.name.type, "String"); assert.equal(json.properties.name.type, "String");
@ -40,7 +39,6 @@ describe('ModelDefinition class', function () {
done(); done();
}); });
it('should be able to define additional properties', function (done) { it('should be able to define additional properties', function (done) {
@ -66,10 +64,8 @@ describe('ModelDefinition class', function () {
assert.equal(User.properties.id.type, Number); assert.equal(User.properties.id.type, Number);
done(); done();
}); });
it('should be able to define nesting models', function (done) { it('should be able to define nesting models', function (done) {
var modelBuilder = new ModelBuilder(); var modelBuilder = new ModelBuilder();
@ -112,7 +108,6 @@ describe('ModelDefinition class', function () {
}); });
it('should be able to define referencing models', function (done) { it('should be able to define referencing models', function (done) {
var modelBuilder = new ModelBuilder(); var modelBuilder = new ModelBuilder();
@ -140,7 +135,6 @@ describe('ModelDefinition class', function () {
assert.equal(User.properties.age.type, Number); assert.equal(User.properties.age.type, Number);
assert.equal(User.properties.address.type, Address); assert.equal(User.properties.address.type, Address);
var json = User.toJSON(); var json = User.toJSON();
assert.equal(json.name, "User"); assert.equal(json.name, "User");
assert.equal(json.properties.name.type, "String"); assert.equal(json.properties.name.type, "String");
@ -182,7 +176,6 @@ describe('ModelDefinition class', function () {
assert.equal(User.properties.age.type, Number); assert.equal(User.properties.age.type, Number);
assert.equal(User.properties.address.type, Address); assert.equal(User.properties.address.type, Address);
var json = User.toJSON(); var json = User.toJSON();
assert.equal(json.name, "User"); assert.equal(json.name, "User");
assert.equal(json.properties.name.type, "String"); assert.equal(json.properties.name.type, "String");

View File

@ -15,14 +15,12 @@ schemas =
url: 'http://localhost:5984/nano-test' url: 'http://localhost:5984/nano-test'
testOrm = (dataSource) -> testOrm = (dataSource) ->
User = Post = 'unknown' User = Post = 'unknown'
maxUsers = 100 maxUsers = 100
maxPosts = 50000 maxPosts = 50000
users = [] users = []
it 'should define simple', (test) -> it 'should define simple', (test) ->
User = dataSource.define 'User', { User = dataSource.define 'User', {
name: String, name: String,
bio: Text, bio: Text,
@ -51,7 +49,8 @@ testOrm = (dataSource) ->
it 'should create bunch of data', (test) -> it 'should create bunch of data', (test) ->
wait = maxPosts wait = maxPosts
done = -> test.done() if --wait == 0 done = ->
test.done() if --wait == 0
rnd = (title) -> rnd = (title) ->
{ {
userId: users[Math.floor(Math.random() * maxUsers)].id userId: users[Math.floor(Math.random() * maxUsers)].id
@ -61,11 +60,13 @@ testOrm = (dataSource) ->
it 'do some queries using foreign keys', (test) -> it 'do some queries using foreign keys', (test) ->
wait = 4 wait = 4
done = -> test.done() if --wait == 0 done = ->
test.done() if --wait == 0
ts = Date.now() ts = Date.now()
query = (num) -> query = (num) ->
users[num].posts { title: 'Post number 3' }, (err, collection) -> users[num].posts { title: 'Post number 3' }, (err, collection) ->
console.log('User ' + num + ':', collection.length, 'posts in', Date.now() - ts,'ms') console.log('User ' + num + ':', collection.length, 'posts in',
Date.now() - ts, 'ms')
done() done()
query num for num in [0..4] query num for num in [0..4]

View File

@ -3,18 +3,18 @@ var should = require('./init.js');
var db, Book, Chapter, Author, Reader; var db, Book, Chapter, Author, Reader;
describe('relations', function() { describe('relations', function () {
before(function(done) { before(function (done) {
db = getSchema(); db = getSchema();
Book = db.define('Book', {name: String}); Book = db.define('Book', {name: String});
Chapter = db.define('Chapter', {name: {type: String, index: true}}); Chapter = db.define('Chapter', {name: {type: String, index: true}});
Author = db.define('Author', {name: String}); Author = db.define('Author', {name: String});
Reader = db.define('Reader', {name: String}); Reader = db.define('Reader', {name: String});
db.automigrate(function() { db.automigrate(function () {
Book.destroyAll(function() { Book.destroyAll(function () {
Chapter.destroyAll(function() { Chapter.destroyAll(function () {
Author.destroyAll(function() { Author.destroyAll(function () {
Reader.destroyAll(done); Reader.destroyAll(done);
}); });
}); });
@ -22,12 +22,12 @@ describe('relations', function() {
}); });
}); });
after(function() { after(function () {
db.disconnect(); db.disconnect();
}); });
describe('hasMany', function() { describe('hasMany', function () {
it('can be declared in different ways', function(done) { it('can be declared in different ways', function (done) {
Book.hasMany(Chapter); Book.hasMany(Chapter);
Book.hasMany(Reader, {as: 'users'}); Book.hasMany(Reader, {as: 'users'});
Book.hasMany(Author, {foreignKey: 'projectId'}); Book.hasMany(Author, {foreignKey: 'projectId'});
@ -41,7 +41,7 @@ describe('relations', function() {
db.automigrate(done); db.automigrate(done);
}); });
it('can be declared in short form', function(done) { it('can be declared in short form', function (done) {
Author.hasMany('readers'); Author.hasMany('readers');
(new Author).readers.should.be.an.instanceOf(Function); (new Author).readers.should.be.an.instanceOf(Function);
Object.keys((new Reader).toObject()).should.include('authorId'); Object.keys((new Reader).toObject()).should.include('authorId');
@ -49,17 +49,17 @@ describe('relations', function() {
db.autoupdate(done); db.autoupdate(done);
}); });
it('should build record on scope', function(done) { it('should build record on scope', function (done) {
Book.create(function(err, book) { Book.create(function (err, book) {
var c = book.chapters.build(); var c = book.chapters.build();
c.bookId.should.equal(book.id); c.bookId.should.equal(book.id);
c.save(done); c.save(done);
}); });
}); });
it('should create record on scope', function(done) { it('should create record on scope', function (done) {
Book.create(function(err, book) { Book.create(function (err, book) {
book.chapters.create(function(err, c) { book.chapters.create(function (err, c) {
should.not.exist(err); should.not.exist(err);
should.exist(c); should.exist(c);
c.bookId.should.equal(book.id); c.bookId.should.equal(book.id);
@ -68,23 +68,23 @@ describe('relations', function() {
}); });
}); });
it.skip('should fetch all scoped instances', function(done) { it.skip('should fetch all scoped instances', function (done) {
Book.create(function(err, book) { Book.create(function (err, book) {
book.chapters.create({name: 'a'}, function() { book.chapters.create({name: 'a'}, function () {
book.chapters.create({name: 'z'}, function() { book.chapters.create({name: 'z'}, function () {
book.chapters.create({name: 'c'}, function() { book.chapters.create({name: 'c'}, function () {
fetch(book); fetch(book);
}); });
}); });
}); });
}); });
function fetch(book) { function fetch(book) {
book.chapters(function(err, ch) { book.chapters(function (err, ch) {
should.not.exist(err); should.not.exist(err);
should.exist(ch); should.exist(ch);
ch.should.have.lengthOf(3); ch.should.have.lengthOf(3);
book.chapters({order: 'name DESC'}, function(e, c) { book.chapters({order: 'name DESC'}, function (e, c) {
should.not.exist(e); should.not.exist(e);
should.exist(c); should.exist(c);
c.shift().name.should.equal('z'); c.shift().name.should.equal('z');
@ -95,13 +95,13 @@ describe('relations', function() {
} }
}); });
it('should find scoped record', function(done) { it('should find scoped record', function (done) {
var id; var id;
Book.create(function(err, book) { Book.create(function (err, book) {
book.chapters.create({name: 'a'}, function(err, ch) { book.chapters.create({name: 'a'}, function (err, ch) {
id = ch.id; id = ch.id;
book.chapters.create({name: 'z'}, function() { book.chapters.create({name: 'z'}, function () {
book.chapters.create({name: 'c'}, function() { book.chapters.create({name: 'c'}, function () {
fetch(book); fetch(book);
}); });
}); });
@ -109,7 +109,7 @@ describe('relations', function() {
}); });
function fetch(book) { function fetch(book) {
book.chapters.findById(id, function(err, ch) { book.chapters.findById(id, function (err, ch) {
should.not.exist(err); should.not.exist(err);
should.exist(ch); should.exist(ch);
ch.id.should.equal(id); ch.id.should.equal(id);
@ -119,10 +119,10 @@ describe('relations', function() {
}); });
}); });
describe('belongsTo', function() { describe('belongsTo', function () {
var List, Item, Fear, Mind; var List, Item, Fear, Mind;
it('can be declared in different ways', function() { it('can be declared in different ways', function () {
List = db.define('List', {name: String}); List = db.define('List', {name: String});
Item = db.define('Item', {name: String}); Item = db.define('Item', {name: String});
Fear = db.define('Fear'); Fear = db.define('Fear');
@ -140,14 +140,14 @@ describe('relations', function() {
// (new Fear).mind.build().should.be.an.instanceOf(Mind); // (new Fear).mind.build().should.be.an.instanceOf(Mind);
}); });
it('can be used to query data', function(done) { it('can be used to query data', function (done) {
List.hasMany('todos', {model: Item}); List.hasMany('todos', {model: Item});
db.automigrate(function() { db.automigrate(function () {
List.create(function(e, list) { List.create(function (e, list) {
should.not.exist(e); should.not.exist(e);
should.exist(list); should.exist(list);
list.todos.create(function(err, todo) { list.todos.create(function (err, todo) {
todo.list(function(e, l) { todo.list(function (e, l) {
should.not.exist(e); should.not.exist(e);
should.exist(l); should.exist(l);
l.should.be.an.instanceOf(List); l.should.be.an.instanceOf(List);
@ -159,11 +159,11 @@ describe('relations', function() {
}); });
}); });
it('could accept objects when creating on scope', function(done) { it('could accept objects when creating on scope', function (done) {
List.create(function(e, list) { List.create(function (e, list) {
should.not.exist(e); should.not.exist(e);
should.exist(list); should.exist(list);
Item.create({list: list}, function(err, item) { Item.create({list: list}, function (err, item) {
should.not.exist(err); should.not.exist(err);
should.exist(item); should.exist(item);
should.exist(item.listId); should.exist(item.listId);
@ -176,28 +176,28 @@ describe('relations', function() {
}); });
describe('hasAndBelongsToMany', function() { describe('hasAndBelongsToMany', function () {
var Article, Tag, ArticleTag; var Article, Tag, ArticleTag;
it('can be declared', function(done) { it('can be declared', function (done) {
Article = db.define('Article', {title: String}); Article = db.define('Article', {title: String});
Tag = db.define('Tag', {name: String}); Tag = db.define('Tag', {name: String});
Article.hasAndBelongsToMany('tags'); Article.hasAndBelongsToMany('tags');
ArticleTag = db.models.ArticleTag; ArticleTag = db.models.ArticleTag;
db.automigrate(function() { db.automigrate(function () {
Article.destroyAll(function() { Article.destroyAll(function () {
Tag.destroyAll(function() { Tag.destroyAll(function () {
ArticleTag.destroyAll(done) ArticleTag.destroyAll(done)
}); });
}); });
}); });
}); });
it('should allow to create instances on scope', function(done) { it('should allow to create instances on scope', function (done) {
Article.create(function(e, article) { Article.create(function (e, article) {
article.tags.create({name: 'popular'}, function(e, t) { article.tags.create({name: 'popular'}, function (e, t) {
t.should.be.an.instanceOf(Tag); t.should.be.an.instanceOf(Tag);
// console.log(t); // console.log(t);
ArticleTag.findOne(function(e, at) { ArticleTag.findOne(function (e, at) {
should.exist(at); should.exist(at);
at.tagId.toString().should.equal(t.id.toString()); at.tagId.toString().should.equal(t.id.toString());
at.articleId.toString().should.equal(article.id.toString()); at.articleId.toString().should.equal(article.id.toString());
@ -207,9 +207,9 @@ describe('relations', function() {
}); });
}); });
it('should allow to fetch scoped instances', function(done) { it('should allow to fetch scoped instances', function (done) {
Article.findOne(function(e, article) { Article.findOne(function (e, article) {
article.tags(function(e, tags) { article.tags(function (e, tags) {
should.not.exist(e); should.not.exist(e);
should.exist(tags); should.exist(tags);
done(); done();
@ -217,10 +217,10 @@ describe('relations', function() {
}); });
}); });
it('should allow to add connection with instance', function(done) { it('should allow to add connection with instance', function (done) {
Article.findOne(function(e, article) { Article.findOne(function (e, article) {
Tag.create({name: 'awesome'}, function(e, tag) { Tag.create({name: 'awesome'}, function (e, tag) {
article.tags.add(tag, function(e, at) { article.tags.add(tag, function (e, at) {
should.not.exist(e); should.not.exist(e);
should.exist(at); should.exist(at);
at.should.be.an.instanceOf(ArticleTag); at.should.be.an.instanceOf(ArticleTag);
@ -232,14 +232,14 @@ describe('relations', function() {
}); });
}); });
it('should allow to remove connection with instance', function(done) { it('should allow to remove connection with instance', function (done) {
Article.findOne(function(e, article) { Article.findOne(function (e, article) {
article.tags(function(e, tags) { article.tags(function (e, tags) {
var len = tags.length; var len = tags.length;
tags.should.not.be.empty; tags.should.not.be.empty;
article.tags.remove(tags[0], function(e) { article.tags.remove(tags[0], function (e) {
should.not.exist(e); should.not.exist(e);
article.tags(true, function(e, tags) { article.tags(true, function (e, tags) {
tags.should.have.lengthOf(len - 1); tags.should.have.lengthOf(len - 1);
done(); done();
}); });

View File

@ -3,16 +3,16 @@ var should = require('./init.js');
var db = getSchema(), slave = getSchema(), Model, SlaveModel; var db = getSchema(), slave = getSchema(), Model, SlaveModel;
describe('dataSource', function() { describe('dataSource', function () {
it('should define Model', function() { it('should define Model', function () {
Model = db.define('Model'); Model = db.define('Model');
Model.dataSource.should.eql(db); Model.dataSource.should.eql(db);
var m = new Model; var m = new Model;
m.getDataSource().should.eql(db); m.getDataSource().should.eql(db);
}); });
it('should clone existing model', function() { it('should clone existing model', function () {
SlaveModel = slave.copyModel(Model); SlaveModel = slave.copyModel(Model);
SlaveModel.dataSource.should.eql(slave); SlaveModel.dataSource.should.eql(slave);
slave.should.not.eql(db); slave.should.not.eql(db);
@ -22,11 +22,11 @@ describe('dataSource', function() {
sm.getDataSource().should.eql(slave); sm.getDataSource().should.eql(slave);
}); });
it('should automigrate', function(done) { it('should automigrate', function (done) {
db.automigrate(done); db.automigrate(done);
}); });
it('should create transaction', function(done) { it('should create transaction', function (done) {
var tr = db.transaction(); var tr = db.transaction();
tr.connected.should.be.false; tr.connected.should.be.false;
tr.connecting.should.be.false; tr.connecting.should.be.false;
@ -37,15 +37,15 @@ describe('dataSource', function() {
tr.connected.should.be.false; tr.connected.should.be.false;
tr.connecting.should.be.true; tr.connecting.should.be.true;
db.models.Model.count(function(err, c) { db.models.Model.count(function (err, c) {
should.not.exist(err); should.not.exist(err);
should.exist(c); should.exist(c);
c.should.equal(0); c.should.equal(0);
called.should.be.false; called.should.be.false;
tr.exec(function () { tr.exec(function () {
setTimeout(function() { setTimeout(function () {
called.should.be.true; called.should.be.true;
db.models.Model.count(function(err, c) { db.models.Model.count(function (err, c) {
c.should.equal(3); c.should.equal(3);
done(); done();
}); });

View File

@ -3,9 +3,9 @@ var should = require('./init.js');
var db, Railway, Station; var db, Railway, Station;
describe('sc0pe', function() { describe('sc0pe', function () {
before(function() { before(function () {
db = getSchema(); db = getSchema();
Railway = db.define('Railway', { Railway = db.define('Railway', {
URID: {type: String, index: true} URID: {type: String, index: true}
@ -19,15 +19,15 @@ describe('sc0pe', function() {
}); });
}); });
beforeEach(function(done) { beforeEach(function (done) {
Railway.destroyAll(function() { Railway.destroyAll(function () {
Station.destroyAll(done); Station.destroyAll(done);
}); });
}); });
it('should define scope with query', function(done) { it('should define scope with query', function (done) {
Station.scope('active', {where: {isActive: true}}); Station.scope('active', {where: {isActive: true}});
Station.active.create(function(err, station) { Station.active.create(function (err, station) {
should.not.exist(err); should.not.exist(err);
should.exist(station); should.exist(station);
should.exist(station.isActive); should.exist(station.isActive);
@ -36,10 +36,10 @@ describe('sc0pe', function() {
}); });
}); });
it('should allow scope chaining', function(done) { it('should allow scope chaining', function (done) {
Station.scope('active', {where: {isActive: true}}); Station.scope('active', {where: {isActive: true}});
Station.scope('subway', {where: {isUndeground: true}}); Station.scope('subway', {where: {isUndeground: true}});
Station.active.subway.create(function(err, station) { Station.active.subway.create(function (err, station) {
should.not.exist(err); should.not.exist(err);
should.exist(station); should.exist(station);
station.isActive.should.be.true; station.isActive.should.be.true;
@ -48,13 +48,13 @@ describe('sc0pe', function() {
}) })
}); });
it('should query all', function(done) { it('should query all', function (done) {
Station.scope('active', {where: {isActive: true}}); Station.scope('active', {where: {isActive: true}});
Station.scope('inactive', {where: {isActive: false}}); Station.scope('inactive', {where: {isActive: false}});
Station.scope('ground', {where: {isUndeground: true}}); Station.scope('ground', {where: {isUndeground: true}});
Station.active.ground.create(function() { Station.active.ground.create(function () {
Station.inactive.ground.create(function() { Station.inactive.ground.create(function () {
Station.ground.inactive(function(err, ss) { Station.ground.inactive(function (err, ss) {
ss.should.have.lengthOf(1); ss.should.have.lengthOf(1);
done(); done();
}); });

View File

@ -1,10 +1,10 @@
/* /*
if (!process.env.TRAVIS) { if (!process.env.TRAVIS) {
var semicov = require('semicov'); var semicov = require('semicov');
semicov.init('lib', 'LoopbackData'); semicov.init('lib', 'LoopbackData');
process.on('exit', semicov.report); process.on('exit', semicov.report);
} }
*/ */
try { try {
global.sinon = require('sinon'); global.sinon = require('sinon');

View File

@ -4,10 +4,8 @@ var fieldsToArray = utils.fieldsToArray;
var removeUndefined = utils.removeUndefined; var removeUndefined = utils.removeUndefined;
var mergeSettings = utils.mergeSettings; var mergeSettings = utils.mergeSettings;
describe('util.fieldsToArray', function () {
describe('util.fieldsToArray', function(){ it('Turn objects and strings into an array of fields to include when finding models', function () {
it('Turn objects and strings into an array of fields to include when finding models', function() {
function sample(fields) { function sample(fields) {
var properties = ['foo', 'bar', 'bat', 'baz']; var properties = ['foo', 'bar', 'bat', 'baz'];
@ -30,8 +28,8 @@ describe('util.fieldsToArray', function(){
}); });
}); });
describe('util.removeUndefined', function(){ describe('util.removeUndefined', function () {
it('Remove undefined values from the query object', function() { it('Remove undefined values from the query object', function () {
var q1 = {where: {x: 1, y: undefined}}; var q1 = {where: {x: 1, y: undefined}};
should.deepEqual(removeUndefined(q1), {where: {x: 1}}); should.deepEqual(removeUndefined(q1), {where: {x: 1}});
@ -54,8 +52,8 @@ describe('util.removeUndefined', function(){
}); });
}); });
describe('util.parseSettings', function(){ describe('util.parseSettings', function () {
it('Parse a full url into a settings object', function() { it('Parse a full url into a settings object', function () {
var url = 'mongodb://x:y@localhost:27017/mydb?w=2'; var url = 'mongodb://x:y@localhost:27017/mydb?w=2';
var settings = utils.parseSettings(url); var settings = utils.parseSettings(url);
should.equal(settings.hostname, 'localhost'); should.equal(settings.hostname, 'localhost');
@ -70,7 +68,7 @@ describe('util.parseSettings', function(){
}); });
it('Parse a url without auth into a settings object', function() { it('Parse a url without auth into a settings object', function () {
var url = 'mongodb://localhost:27017/mydb/abc?w=2'; var url = 'mongodb://localhost:27017/mydb/abc?w=2';
var settings = utils.parseSettings(url); var settings = utils.parseSettings(url);
should.equal(settings.hostname, 'localhost'); should.equal(settings.hostname, 'localhost');
@ -85,7 +83,7 @@ describe('util.parseSettings', function(){
}); });
it('Parse a url with complex query into a settings object', function() { it('Parse a url with complex query into a settings object', function () {
var url = 'mysql://127.0.0.1:3306/mydb?x[a]=1&x[b]=2&engine=InnoDB'; var url = 'mysql://127.0.0.1:3306/mydb?x[a]=1&x[b]=2&engine=InnoDB';
var settings = utils.parseSettings(url); var settings = utils.parseSettings(url);
should.equal(settings.hostname, '127.0.0.1'); should.equal(settings.hostname, '127.0.0.1');
@ -102,7 +100,7 @@ describe('util.parseSettings', function(){
}); });
it('Parse a url without auth into a settings object', function() { it('Parse a url without auth into a settings object', function () {
var url = 'memory://?x=1'; var url = 'memory://?x=1';
var settings = utils.parseSettings(url); var settings = utils.parseSettings(url);
should.equal(settings.hostname, ''); should.equal(settings.hostname, '');

View File

@ -16,9 +16,9 @@ function getValidAttributes() {
}; };
} }
describe('validations', function() { describe('validations', function () {
before(function(done) { before(function (done) {
db = getSchema(); db = getSchema();
User = db.define('User', { User = db.define('User', {
email: String, email: String,
@ -36,22 +36,22 @@ describe('validations', function() {
db.automigrate(done); db.automigrate(done);
}); });
beforeEach(function(done) { beforeEach(function (done) {
User.destroyAll(function() { User.destroyAll(function () {
delete User._validations; delete User._validations;
done(); done();
}); });
}); });
after(function() { after(function () {
db.disconnect(); db.disconnect();
}); });
describe('commons', function() { describe('commons', function () {
describe('skipping', function() { describe('skipping', function () {
it('should allow to skip using if: attribute', function() { it('should allow to skip using if: attribute', function () {
User.validatesPresenceOf('pendingPeriod', {if: 'createdByAdmin'}); User.validatesPresenceOf('pendingPeriod', {if: 'createdByAdmin'});
var user = new User; var user = new User;
user.createdByAdmin = true; user.createdByAdmin = true;
@ -63,29 +63,29 @@ describe('validations', function() {
}); });
describe('lifecycle', function() { describe('lifecycle', function () {
it('should work on create', function(done) { it('should work on create', function (done) {
delete User._validations; delete User._validations;
User.validatesPresenceOf('name'); User.validatesPresenceOf('name');
User.create(function(e, u) { User.create(function (e, u) {
should.exist(e); should.exist(e);
User.create({name: 'Valid'}, function(e, d) { User.create({name: 'Valid'}, function (e, d) {
should.not.exist(e); should.not.exist(e);
done(); done();
}); });
}); });
}); });
it('should work on update', function(done) { it('should work on update', function (done) {
delete User._validations; delete User._validations;
User.validatesPresenceOf('name'); User.validatesPresenceOf('name');
User.create({name: 'Valid'}, function(e, d) { User.create({name: 'Valid'}, function (e, d) {
d.updateAttribute('name', null, function(e) { d.updateAttribute('name', null, function (e) {
should.exist(e); should.exist(e);
e.should.be.instanceOf(Error); e.should.be.instanceOf(Error);
e.should.be.instanceOf(ValidationError); e.should.be.instanceOf(ValidationError);
d.updateAttribute('name', 'Vasiliy', function(e) { d.updateAttribute('name', 'Vasiliy', function (e) {
should.not.exist(e); should.not.exist(e);
done(); done();
}); });
@ -93,18 +93,18 @@ describe('validations', function() {
}); });
}); });
it('should return error code', function(done) { it('should return error code', function (done) {
delete User._validations; delete User._validations;
User.validatesPresenceOf('name'); User.validatesPresenceOf('name');
User.create(function(e, u) { User.create(function (e, u) {
should.exist(e); should.exist(e);
e.details.codes.name.should.eql(['presence']); e.details.codes.name.should.eql(['presence']);
done(); done();
}); });
}); });
it('should allow to modify error after validation', function(done) { it('should allow to modify error after validation', function (done) {
User.afterValidate = function(next) { User.afterValidate = function (next) {
next(); next();
}; };
done(); done();
@ -113,9 +113,9 @@ describe('validations', function() {
}); });
}); });
describe('presence', function() { describe('presence', function () {
it('should validate presence', function() { it('should validate presence', function () {
User.validatesPresenceOf('name', 'email'); User.validatesPresenceOf('name', 'email');
var u = new User; var u = new User;
u.isValid().should.not.be.true; u.isValid().should.not.be.true;
@ -124,7 +124,7 @@ describe('validations', function() {
u.isValid().should.be.true; u.isValid().should.be.true;
}); });
it('should skip validation by property (if/unless)', function() { it('should skip validation by property (if/unless)', function () {
User.validatesPresenceOf('domain', {unless: 'createdByScript'}); User.validatesPresenceOf('domain', {unless: 'createdByScript'});
var user = new User(getValidAttributes()) var user = new User(getValidAttributes())
@ -140,15 +140,15 @@ describe('validations', function() {
}); });
describe('uniqueness', function() { describe('uniqueness', function () {
it('should validate uniqueness', function(done) { it('should validate uniqueness', function (done) {
User.validatesUniquenessOf('email'); User.validatesUniquenessOf('email');
var u = new User({email: 'hey'}); var u = new User({email: 'hey'});
Boolean(u.isValid(function(valid) { Boolean(u.isValid(function (valid) {
valid.should.be.true; valid.should.be.true;
u.save(function() { u.save(function () {
var u2 = new User({email: 'hey'}); var u2 = new User({email: 'hey'});
u2.isValid(function(valid) { u2.isValid(function (valid) {
valid.should.be.false; valid.should.be.false;
done(); done();
}); });
@ -156,14 +156,14 @@ describe('validations', function() {
})).should.be.false; })).should.be.false;
}); });
it('should handle same object modification', function(done) { it('should handle same object modification', function (done) {
User.validatesUniquenessOf('email'); User.validatesUniquenessOf('email');
var u = new User({email: 'hey'}); var u = new User({email: 'hey'});
Boolean(u.isValid(function(valid) { Boolean(u.isValid(function (valid) {
valid.should.be.true; valid.should.be.true;
u.save(function() { u.save(function () {
u.name = 'Goghi'; u.name = 'Goghi';
u.isValid(function(valid) { u.isValid(function (valid) {
valid.should.be.true; valid.should.be.true;
u.save(done); u.save(done);
}); });
@ -174,28 +174,28 @@ describe('validations', function() {
}); });
describe('format', function() { describe('format', function () {
it('should validate format'); it('should validate format');
it('should overwrite default blank message with custom format message'); it('should overwrite default blank message with custom format message');
}); });
describe('numericality', function() { describe('numericality', function () {
it('should validate numericality'); it('should validate numericality');
}); });
describe('inclusion', function() { describe('inclusion', function () {
it('should validate inclusion'); it('should validate inclusion');
}); });
describe('exclusion', function() { describe('exclusion', function () {
it('should validate exclusion'); it('should validate exclusion');
}); });
describe('length', function() { describe('length', function () {
it('should validate length'); it('should validate length');
}); });
describe('custom', function() { describe('custom', function () {
it('should validate using custom sync validation'); it('should validate using custom sync validation');
it('should validate using custom async validation'); it('should validate using custom async validation');
}); });