downstairs
Advanced tools
Comparing version 0.2.10 to 0.3.0a
@@ -7,4 +7,2 @@ var Collection = {} | ||
Collection.Downstairs; | ||
Collection.use = function(Downstairs){ | ||
@@ -14,2 +12,43 @@ Collection.Downstairs = Downstairs; | ||
/* | ||
* Custom callbacks | ||
*/ | ||
Collection.when = function(callbackName, callback){ | ||
this.callbacks[callbackName] = callback; | ||
} | ||
Collection.runModelCallbacks = function(modelCallbacks, data, cb){ | ||
var record = this; | ||
var caller = function(modelCallbackName, _cb){ | ||
record.callbacks[modelCallbackName](data, _cb); | ||
} | ||
async.forEach(modelCallbacks, caller, function(err){ | ||
return cb(err, data); | ||
}); | ||
} | ||
/* | ||
* Eventing | ||
*/ | ||
Collection.on = function(eventName, whenFunction){ | ||
this.prototype.on(eventName, whenFunction); | ||
} | ||
Collection.emitQueryEvents = function(queryEvents, data){ | ||
var record = this; | ||
var eventEmitter = function(eventName){ | ||
record.prototype.emit(eventName, data); | ||
} | ||
async.forEach(queryEvents, eventEmitter); | ||
} | ||
/* | ||
* SQL specific CRUD behaviours. | ||
*/ | ||
var jsonConditionsToSQL = function(Model, conditions){ | ||
@@ -27,3 +66,2 @@ var clauses = []; | ||
} | ||
} | ||
@@ -47,5 +85,5 @@ } | ||
var parseConditions = function (conditions, _self, sqlBaseQuery) { | ||
var parseConditions = function (conditions, self, sqlBaseQuery) { | ||
if (conditions){ | ||
var sqlConditions = jsonConditionsToSQL(_self, conditions); | ||
var sqlConditions = jsonConditionsToSQL(self, conditions); | ||
if (sqlConditions) { | ||
@@ -73,17 +111,18 @@ return sqlBaseQuery.where(sqlConditions); | ||
*/ | ||
Collection.findAll = function(conditions, cb){ | ||
var results = []; | ||
if (typeof conditions === 'function') { | ||
cb = conditions; | ||
conditions = null; | ||
Collection.getConnection = function(){ | ||
if (!this.connection.connectionString) { | ||
this.connection.connectionString = this.Downstairs.connectionString; | ||
} | ||
var sqlStr; | ||
var sqlBaseQuery = this.sql.select(this.sql.star()).from(this.sql); | ||
sqlBaseQuery = parseConditions(conditions, this, sqlBaseQuery); | ||
sqlStr = sqlBaseQuery.toQuery(); | ||
return this.connection; | ||
} | ||
select = function(model, conditions, cb){ | ||
var sqlBaseQuery = model.sql.select(model.sql.star()).from(model.sql); | ||
sqlBaseQuery = parseConditions(conditions, model, sqlBaseQuery); | ||
var sqlStr = sqlBaseQuery.toQuery(); | ||
if (conditions && conditions.queryParameters){ | ||
if (conditions.queryParameters.orderBy){ | ||
@@ -102,27 +141,42 @@ sqlStr.text = sqlStr.text + " ORDER BY " + conditions.queryParameters['orderBy']; | ||
var _self = this; | ||
var _cb = cb; | ||
model.getConnection().query(sqlStr, cb); | ||
} | ||
var finderAllCb = function(err, results){ | ||
var models = []; | ||
Collection.findAll = function(conditions, cb){ | ||
var modelCallbacks, queryEvents; | ||
if (typeof conditions === 'function') { | ||
cb = conditions; | ||
} | ||
if (conditions) { | ||
modelCallbacks = conditions.callbacks; | ||
delete conditions.callbacks; | ||
queryEvents = conditions.emit; | ||
delete conditions.emit; | ||
} | ||
var self = this; | ||
select(this, conditions, function(err, results){ | ||
var records = []; | ||
if (results){ | ||
for (var i in results.rows){ | ||
var model = new _self(results.rows[i]); | ||
models.push(model); | ||
var record = new self(results.rows[i]); | ||
records.push(record); | ||
} | ||
} | ||
_cb(err, models); | ||
} | ||
if (!this.connection.connectionString) { | ||
this.connection.connectionString = this.Downstairs.connectionString; | ||
} | ||
this.connection.query(sqlStr, finderAllCb); | ||
endQuery(self, queryEvents, modelCallbacks, records, cb, err); | ||
}); | ||
}; | ||
Collection.find = function(conditions, cb){ | ||
var modelCallbacks = conditions.callbacks; | ||
delete conditions.callbacks; | ||
var queryEvents = conditions.emit; | ||
delete conditions.emit; | ||
if (typeof conditions === 'function') { | ||
@@ -133,14 +187,33 @@ cb = conditions; | ||
var findCb = function(err, models){ | ||
if (models && models[0]) { | ||
cb(err, models[0]); | ||
var self = this; | ||
select(this, conditions, function(err, results){ | ||
var record; | ||
if (results.rows[0]){ | ||
record = new self(results.rows[0]); | ||
endQuery(self, queryEvents, modelCallbacks, record, cb, err); | ||
} | ||
else { | ||
cb(err, null); | ||
cb(err, record); | ||
} | ||
}); | ||
}; | ||
var endQuery = function(model, queryEvents, modelCallbacks, data, cb, err){ | ||
if (err){ | ||
return cb(err, null); | ||
} | ||
this.findAll(conditions, findCb); | ||
}; | ||
if (queryEvents){ | ||
model.emitQueryEvents(queryEvents, data); | ||
} | ||
if (modelCallbacks){ | ||
model.runModelCallbacks(modelCallbacks, data, cb); | ||
} | ||
else { | ||
cb(null, data); | ||
} | ||
} | ||
Collection.count = function(conditions, cb){ | ||
@@ -154,72 +227,39 @@ var results = []; | ||
var sqlStr; | ||
var sqlBaseQuery = this.sql.select('COUNT(*)').from(this.sql); | ||
sqlBaseQuery = parseConditions(conditions, this, sqlBaseQuery); | ||
sqlStr = sqlBaseQuery.toQuery(); | ||
var sqlStr = sqlBaseQuery.toQuery(); | ||
var _self = this; | ||
var _cb = cb; | ||
if (!this.connection.connectionString) { | ||
this.connection.connectionString = this.Downstairs.connectionString; | ||
} | ||
var countCb = function(err, results){ | ||
if (results && results.rows && results.rows[0] && results.rows[0].count) { | ||
_cb(err, results.rows[0].count); | ||
this.connection.query(sqlStr, function(err, results){ | ||
if (results && results.rows && results.rows[0]) { | ||
cb(err, results.rows[0].count); | ||
} | ||
else { | ||
_cb(err, 0); | ||
cb(err, 0); | ||
} | ||
} | ||
if (!this.connection.connectionString) { | ||
this.connection.connectionString = this.Downstairs.connectionString; | ||
} | ||
this.connection.query(sqlStr, countCb); | ||
}); | ||
}; | ||
Collection.update = function(data, conditions, cb){ | ||
if (typeof data === 'function'){ | ||
cb = data; | ||
data = null; | ||
conditions = null; | ||
} | ||
data = cleanData(this.sql, data); | ||
if (typeof conditions === 'function') { | ||
cb = conditions; | ||
conditions = null; | ||
} | ||
if (!conditions && data) { | ||
if (data.nodes && data.left && data.right) { | ||
// Sniff for a where clause condition object | ||
conditions = data; | ||
data = null; | ||
} | ||
} | ||
var sqlBaseQuery = this.sql.update(data); | ||
var _cb = cb; | ||
if (!data || typeof data === 'function') { | ||
return _cb({message: 'No data was provided'}, false); | ||
} | ||
data = cleanData(this.sql, data); | ||
var sqlStr; | ||
var sqlBaseQuery = this.sql.update(data); | ||
sqlBaseQuery = parseConditions(conditions, this, sqlBaseQuery); | ||
sqlStr = sqlBaseQuery.toQuery(); | ||
var sqlStr = sqlBaseQuery.toQuery(); | ||
sqlStr.text = sqlStr.text + " RETURNING id;" | ||
var _self = this; | ||
var updateCb = function(err, results){ | ||
var self = this; | ||
this.connection.query(sqlStr, function(err, results){ | ||
if (results && results.rowCount > 0) { | ||
return _self.find({id: results.rows[0].id}, cb); | ||
return self.find({id: results.rows[0].id}, cb); | ||
} | ||
_cb(err, null); | ||
} | ||
this.connection.query(sqlStr, updateCb); | ||
cb(err, null); | ||
}); | ||
} | ||
@@ -233,24 +273,15 @@ | ||
var _cb = cb; | ||
if (!data || typeof data === 'function') { | ||
return _cb({message: 'No data was provided'}, false); | ||
} | ||
data = cleanData(this.sql, data); | ||
var sqlStr; | ||
var sqlBaseQuery = this.sql.insert(data); | ||
sqlStr = sqlBaseQuery.toQuery(); | ||
var sqlStr = sqlBaseQuery.toQuery(); | ||
sqlStr.text = sqlStr.text + " RETURNING id;" | ||
var _self = this; | ||
var queries = {}; | ||
var self = this; | ||
_self.connection.query(sqlStr, function(err, result){ | ||
this.connection.query(sqlStr, function(err, result){ | ||
if (err){ return cb(err, result) }; | ||
if (result && result.rowCount > 0) { | ||
return _self.find({id: result.rows[0].id}, cb); | ||
return self.find({id: result.rows[0].id}, cb); | ||
} | ||
@@ -269,10 +300,6 @@ else { | ||
var _cb = cb; | ||
var sqlStr; | ||
var sqlBaseQuery = this.sql.delete(data); | ||
var sqlStr = sqlBaseQuery.toQuery(); | ||
sqlStr = sqlBaseQuery.toQuery(); | ||
var deleteCb = function(err, results) { | ||
this.getConnection().query(sqlStr, function(err, results) { | ||
var result = false; | ||
@@ -283,44 +310,61 @@ if (!err) { | ||
_cb(err, result); | ||
} | ||
this.connection.query(sqlStr, deleteCb); | ||
cb(err, result); | ||
}); | ||
} | ||
/* | ||
* Associations. | ||
*/ | ||
Collection.belongsTo = function(model){ | ||
var belongsToFunctionName = model.name2.toLowerCase(); | ||
var foreignKeyName = belongsToFunctionName + "_id"; //oneday this will be configurable | ||
var belongsToAssociationName = model._name.toLowerCase(); | ||
var foreignKeyName = belongsToAssociationName + "_id"; //oneday this will be configurable | ||
var belongsTo = function(cb){ | ||
return model.find({id: this[foreignKeyName]}, cb) | ||
var record = this; | ||
model.find({id: this[foreignKeyName]}, function(err, belonger){ | ||
record[belongsToAssociationName] = belonger; | ||
cb(err, belonger); | ||
}); | ||
}; | ||
this.prototype[belongsToFunctionName] = belongsTo; | ||
this.prototype['_' + belongsToAssociationName] = belongsTo; | ||
this.prototype[belongsToAssociationName] = null; | ||
} | ||
Collection.hasOne = function(model){ | ||
var keyName = this.name2.toLowerCase(); | ||
var hasOneFunctionName = model.name2; | ||
hasOneFunctionName = hasOneFunctionName.toLowerCase(); | ||
var keyName = this._name.toLowerCase(); | ||
var hasOneAssociationName = model._name; | ||
hasOneAssociationName = hasOneAssociationName.toLowerCase(); | ||
var foreignKeyName = keyName + "_id"; //oneday this will be configurable | ||
var hasOne = function(cb){ | ||
return model.find({id: this[foreignKeyName]}, cb) | ||
var record = this; | ||
model.find({id: this[foreignKeyName]}, function(err, one){ | ||
record[hasOneAssociationName] = one; | ||
cb(err, one); | ||
}); | ||
}; | ||
this.prototype[hasOneFunctionName] = hasOne; | ||
this.prototype['_' + hasOneAssociationName] = hasOne; | ||
this.prototype[hasOneAssociationName] = null; | ||
} | ||
Collection.hasMany = function(model){ | ||
var keyName = this.name2.toLowerCase(); | ||
var hasManyFunctionName = lingo.en.pluralize(model.name2); | ||
hasManyFunctionName = hasManyFunctionName.toLowerCase(); | ||
var keyName = this._name.toLowerCase(); | ||
var hasManyAssociationName = lingo.en.pluralize(model._name); | ||
hasManyAssociationName = hasManyAssociationName.toLowerCase(); | ||
var foreignKeyName = keyName + "_id"; //oneday this will be configurable | ||
var hasMany = function(cb){ | ||
return model.findAll({id: this[foreignKeyName]}, cb) | ||
var record = this; | ||
model.findAll({id: this[foreignKeyName]}, function(err, all){ | ||
record[hasManyAssociationName] = all; | ||
cb(err, all); | ||
}); | ||
}; | ||
this.prototype[hasManyFunctionName] = hasMany; | ||
this.prototype['_' + hasManyAssociationName] = hasMany; | ||
this.prototype[hasManyAssociationName] = []; | ||
} | ||
@@ -358,2 +402,6 @@ | ||
/* | ||
* Model constructor function. Holds all behaviour for the Collection | ||
* that must apply to each Record belonging to it (validation, etc.) | ||
*/ | ||
var Model = function(properties){ | ||
@@ -370,3 +418,3 @@ this.properties = properties; | ||
this[validation] = this.validations[validation]; | ||
var _self = this; | ||
var self = this; | ||
validationCycle.push(createValidator(record, validation)); | ||
@@ -389,6 +437,9 @@ } | ||
} | ||
this.get = function(associationName, cb){ | ||
return this['_' + associationName](cb); | ||
} | ||
}; | ||
Model.name = name; | ||
Model.name2 = name; | ||
Model._name = name; | ||
@@ -403,4 +454,4 @@ Model.prototype = new Record(); | ||
Model.prototype._model = Model; | ||
Model.callbacks = {}; | ||
mixinCollectionFunctions(Model); | ||
@@ -412,3 +463,2 @@ | ||
else { | ||
// console.log(dbConnection.register, " <<<< the dbConnection.register function ... This call is uniform before all tests"); | ||
dbConnection.register(name, Model); | ||
@@ -415,0 +465,0 @@ } |
var async = require('async') | ||
, events = require('events') | ||
, util = require('util') | ||
, _ = require('underscore'); | ||
var fieldsFinder = function(keys, record){ | ||
@@ -16,2 +17,7 @@ var data = {}; | ||
/* | ||
* Record constructor function. Holds data state mapping | ||
* to the abstracted representation of one member of a Collection | ||
* e.g. a row in a sql table, a document in a mongo collection, etc.. | ||
*/ | ||
var Record = function(properties){ | ||
@@ -21,3 +27,2 @@ this._isNew = true; | ||
if (this.id) { this._isNew = false; } | ||
@@ -52,2 +57,7 @@ | ||
/* | ||
* Records are event emitters | ||
*/ | ||
Record.prototype = new events.EventEmitter(); | ||
module.exports = Record; |
{ | ||
"name": "downstairs", | ||
"description": "A light ORM wrapped about brianc's node-sql and node-pg", | ||
"version": "0.2.10", | ||
"version": "0.3.0a", | ||
"homepage": "https://github.com/moneytribeaustralia/downstairs.js", | ||
"author": { | ||
"name": "damienwhaley, nicholasf", | ||
"name": "kristian-puccio, damienwhaley, nicholasf", | ||
"email": "hello@moneytribe.com.au" | ||
@@ -9,0 +9,0 @@ }, |
@@ -37,5 +37,6 @@ var Downstairs = require('../lib/downstairs') | ||
User.find({ username: 'fred', email: 'fred@moneytribe.com.au', role_id: role.id } , function(err, user){ | ||
should.exist(user.role) | ||
user.role( function(err, userRole){ | ||
should.exist(user._role) | ||
user.get('role', function(err, userRole){ | ||
userRole.id.should.equal(role.id); | ||
user.role.id.should.equal(userRole.id); | ||
done(); | ||
@@ -70,10 +71,10 @@ }) | ||
User.find({ username: 'fred', email: 'fred@moneytribe.com.au'} , function(err, user){ | ||
should.exist(user.account); | ||
should.exist(user._account); | ||
ectypes.Account.create({user_id: user.id}, function(err, result){ | ||
Account.find({user_id: user.id}, function(err, account){ | ||
user.account( function(err, userAccount){ | ||
user.get('account', function(err, userAccount){ | ||
account.id.should.equal(userAccount.id); | ||
user.account.id.should.equal(userAccount.id); | ||
done(); | ||
}) | ||
}); | ||
@@ -86,4 +87,2 @@ }) | ||
describe('hasMany', function(done){ | ||
@@ -118,4 +117,5 @@ beforeEach(function(done){ | ||
User.find({ username: 'mary', email: 'mary@moneytribe.com.au', role_id: role.id } , function(err, user){ | ||
role.users( function(err, users){ | ||
role.get('users', function(err, users){ | ||
users.length.should.equal(2); | ||
role.users.length.should.equal(2); | ||
done(); | ||
@@ -122,0 +122,0 @@ }); |
@@ -8,3 +8,3 @@ var Connection = require('./../../lib/connections') | ||
var myDefaultPGConnection; | ||
var pgConnection; | ||
@@ -14,8 +14,8 @@ describe('Connections, assuming that the downstairs_test db exists', function(){ | ||
beforeEach(function() { | ||
myDefaultPGConnection = new Connection.PostgreSQL(env.connectionString); | ||
Downstairs.add(myDefaultPGConnection); | ||
pgConnection = new Connection.PostgreSQL(env.connectionString); | ||
Downstairs.add(pgConnection); | ||
}); | ||
it('can create a default connection object', function() { | ||
should.exist(myDefaultPGConnection); | ||
should.exist(pgConnection); | ||
}); | ||
@@ -26,3 +26,3 @@ | ||
myDefaultPGConnection.query(queryString, function(err, result){ | ||
pgConnection.query(queryString, function(err, result){ | ||
should.not.exist(err); | ||
@@ -40,22 +40,6 @@ should.exist(result); | ||
should.exist(myDefaultPGConnection.modelConstructors); | ||
should.exist(myDefaultPGConnection.modelConstructors.User); | ||
should.exist(pgConnection.modelConstructors); | ||
should.exist(pgConnection.modelConstructors.User); | ||
done(); | ||
}); | ||
}); | ||
// describe('Downstairs', function(){ | ||
// beforeEach(function(done){ | ||
// var fooSQL = "CREATE TABLE foo (id int, name character varying(50));" | ||
// helper.resetDb(fooSQL, done); | ||
// }) | ||
// it('can connect to the database', function(done) { | ||
// Downstairs.go(env.connectionString); | ||
// Downstairs.query('SELECT * FROM foo;', function(err, results) { | ||
// should.exist(results); | ||
// done(); | ||
// }) | ||
// }); | ||
// }); |
@@ -13,5 +13,4 @@ var Downstairs = require('../lib/downstairs') | ||
it('has a connection', function() { | ||
var myDefaultPGConnection; | ||
myDefaultPGConnection = new Connection.PostgreSQL(env.connectionString); | ||
Downstairs.add(myDefaultPGConnection); | ||
var pgConnection = new Connection.PostgreSQL(env.connectionString); | ||
Downstairs.add(pgConnection); | ||
var User = Collection.model('User', helper.userConfig); | ||
@@ -28,5 +27,4 @@ should.exist(User.connection); | ||
it('creates a new Model and returns an instance', function(done) { | ||
var myDefaultPGConnection; | ||
myDefaultPGConnection = new Connection.PostgreSQL(env.connectionString); | ||
Downstairs.add(myDefaultPGConnection); | ||
var pgConnection = new Connection.PostgreSQL(env.connectionString); | ||
Downstairs.add(pgConnection); | ||
@@ -42,2 +40,2 @@ var User = Collection.model('User', helper.userConfig); | ||
}); | ||
}); | ||
}); |
@@ -89,1 +89,60 @@ var Downstairs = require('../lib/downstairs') | ||
}); | ||
describe('defining callbacks on the Model that are run on a Record', function(done){ | ||
beforeEach(function(done) { | ||
helper.resetDb(helper.userSQL + helper.roleSQL, done); | ||
}); | ||
it("a callback for eagerly loading the user's role", function(done) { | ||
var pgConnection = new Connection.PostgreSQL(env.connectionString); | ||
Downstairs.add(pgConnection); | ||
var User = Collection.model('User', helper.userConfig); | ||
var Role = Collection.model('Role', helper.roleConfig); | ||
User.belongsTo(Role) | ||
var loadRole = function(user, cb){ | ||
user.get('role', cb); | ||
}; | ||
User.when('securityDisplay', loadRole); | ||
Role.create({name: 'admin'}, function(err, role){ | ||
User.create({role_id: role.id, username: 'donald'}, function(err, user) { | ||
User.find({id: user.id, callbacks: ['securityDisplay']}, function(err, user){ | ||
user.role.id.should.equal(role.id); | ||
done() | ||
}) | ||
}); | ||
}); | ||
}); | ||
}) | ||
describe('defining events on the Model that are run on a Record', function(done){ | ||
beforeEach(function(done) { | ||
helper.resetDb(helper.userSQL + helper.accountSQL, done); | ||
}); | ||
it("an event for asynchronously creating a dependent", function(done) { | ||
var pgConnection = new Connection.PostgreSQL(env.connectionString); | ||
Downstairs.add(pgConnection); | ||
var User = Collection.model('User', helper.userConfig); | ||
var Account = Collection.model('Account', helper.accountConfig); | ||
var createAccount = function(user){ | ||
Account.create({user_id: user.id}, function(err, account){ | ||
account.user_id.should.equal(user.id); | ||
done(); | ||
}); | ||
}; | ||
User.on('accountCreation', createAccount); | ||
User.create({username: 'donald'}, function(err, user) { | ||
User.find({username: 'donald', emit: ['accountCreation']}, function(err, user){ | ||
}) | ||
}); | ||
}); | ||
}) |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
104685
1556