Comparing version 0.3.48 to 0.3.49
106
lib/Model.js
@@ -21,2 +21,18 @@ !function(){ | ||
// dont create a neested set ionstance if not really used | ||
// the nested set implementation handles all nested set | ||
// specific behaviour | ||
, _nestedSet: { | ||
get: function() { | ||
if (!this.__nestedSet) { | ||
this.__nestedSet = new NestedSet({ | ||
}); | ||
} | ||
return this.__nestedSet; | ||
} | ||
} | ||
, _nestedSetConfig: { | ||
@@ -333,3 +349,3 @@ get: function() { | ||
log.dir(query); | ||
throw new Error('Failed to create proper delete query, no filter was created (see query definition above)'); | ||
throw new Error('Failed to create proper delete query for model «'+this.getEntityName()+'», no filter was created (see query definition above)'); | ||
} | ||
@@ -341,8 +357,15 @@ else { | ||
query.values[this._defintion.deletedTimestamp] = process.env.ORM_TIMESTAMP_VALUE ? new Date(process.env.ORM_TIMESTAMP_VALUE) : new Date(); | ||
this.emit('beforeDelete', this, true); | ||
this._emitOnCommit(transaction, 'afterDeleteCommit', this, true); | ||
transaction.executeQuery('update', query, callback); | ||
} | ||
else transaction.executeQuery('delete', query, callback); | ||
else { | ||
this.emit('beforeDelete', this); | ||
this._emitOnCommit(transaction, 'afterDeleteCommit', this); | ||
transaction.executeQuery('delete', query, callback); | ||
} | ||
} | ||
} | ||
else callback(new Error('Cannot delete model, it wasn\'t loaded from the database!')); | ||
else callback(new Error('Cannot delete model «'+this.getEntityName()+'», it wasn\'t loaded from the database!')); | ||
} | ||
@@ -352,2 +375,10 @@ | ||
/* | ||
* emits a specifc event when a transaction is commited successfull | ||
*/ | ||
, _emitOnCommit: function(transaction, event) { | ||
transaction.once('commit', function(){ | ||
this.emit.apply(this, [event].concat(Array.prototype.slice.call(arguments, 2))); | ||
}.bind(this)); | ||
} | ||
@@ -450,4 +481,4 @@ /* | ||
*/ | ||
, _updateNestedSet: function(transaction, callback) { | ||
this._prepareNestedSetTransaction(transaction, function(err, options) { | ||
, _updateNestedSet: function(transaction, callback) { log.wtf('möving'); | ||
this._prepareNestedSetTransaction(transaction, function(err, options) { log(options); | ||
var moveValues = {} | ||
@@ -619,2 +650,6 @@ , width | ||
// this is a pretty unreliable event, ou are not going to know if the save is going to succeed | ||
this.emit('beforeSave', this); | ||
this._emitOnCommit(transaction, 'afterSaveCommit', this); | ||
// mkae sure the outer callback gets this model | ||
@@ -652,2 +687,4 @@ // as second parameter | ||
if (this._fromDb){ | ||
this.emit('beforeUpdate', this); | ||
if (this._changedValues.length) { | ||
@@ -659,17 +696,24 @@ this._defintion.primaryKeys.forEach(function(key){ | ||
if (this._defintion.updatedTimestamp) query.values[this._defintion.updatedTimestamp] = process.env.ORM_TIMESTAMP_VALUE ? new Date(process.env.ORM_TIMESTAMP_VALUE) : new Date(); | ||
transaction.executeQuery('update', query, function(err){ | ||
var wait; | ||
if (err) callback(err); | ||
else { | ||
wait = async.waiter(callback); | ||
this._updateNestedSet(transaction, wait()); | ||
this._saveChildren(transaction, noReload, wait()); | ||
this.emit('afterUpdate', this, true); | ||
this._emitOnCommit(transaction, 'afterUpdateCommit', this); | ||
this._saveChildren(transaction, noReload, function(err) { | ||
this.emit('afterSave', this, true); | ||
callback(err); | ||
}.bind(this)); | ||
} | ||
}.bind(this)); | ||
} | ||
else this._saveChildren(transaction, noReload, callback); | ||
else this._saveChildren(transaction, noReload, function(err) { | ||
this.emit('afterSave', this, true); | ||
callback(err); | ||
}.bind(this)); | ||
} | ||
else { | ||
this.emit('beforeInsert', this); | ||
if (this._defintion.updatedTimestamp) query.values[this._defintion.updatedTimestamp] = process.env.ORM_TIMESTAMP_VALUE ? new Date(process.env.ORM_TIMESTAMP_VALUE) : new Date(); | ||
@@ -681,5 +725,3 @@ if (this._defintion.createdTimestamp) query.values[this._defintion.createdTimestamp] = process.env.ORM_TIMESTAMP_VALUE ? new Date(process.env.ORM_TIMESTAMP_VALUE) : new Date(); | ||
else { | ||
transaction.executeQuery('insert', query, function(err, result){ | ||
var wait; | ||
transaction.executeQuery('insert', query, function(err, result) { | ||
if (err) callback(err); | ||
@@ -695,3 +737,9 @@ else { | ||
this._saveChildren(transaction, noReload, callback); | ||
this.emit('afterInsert', this); | ||
this._emitOnCommit(transaction, 'afterInsertCommit', this); | ||
this._saveChildren(transaction, noReload, function(err) { | ||
this.emit('afterSave', this, true); | ||
callback(err); | ||
}.bind(this)); | ||
} | ||
@@ -711,2 +759,4 @@ else throw new Error('not implemented!'); | ||
, _saveChildren: function(transaction, noReload, callback) { | ||
this.emit('beforeSaveChildren'); | ||
async.wait(function(done) { | ||
@@ -717,3 +767,6 @@ this._saveMappings(transaction, noReload, done); | ||
this._saveBelongsTo(transaction, noReload, done); | ||
}.bind(this), callback); | ||
}.bind(this), function(err){ | ||
this.emit('afterSaveChildren'); | ||
callback(err); | ||
}.bind(this)); | ||
} | ||
@@ -724,5 +777,9 @@ | ||
, _saveBelongsTo: function(transaction, noReload, callback) { | ||
this.emit('beforeSaveBelongsTo'); | ||
async.each(Object.keys(this._belongsTo), function(belongsToId, next){ | ||
this._belongsTo[belongsToId].save(transaction, noReload, next); | ||
}.bind(this), callback); | ||
}.bind(this), function(err){ | ||
this.emit('afterSaveBelongsTo'); | ||
callback(err); | ||
}.bind(this)); | ||
} | ||
@@ -733,5 +790,9 @@ | ||
, _saveMappings: function(transaction, noReload, callback) { | ||
this.emit('beforeSaveMappings'); | ||
async.each(Object.keys(this._mappings), function(mappingId, next){ | ||
this._mappings[mappingId].save(transaction, noReload, next); | ||
}.bind(this), callback); | ||
}.bind(this), function(err){ | ||
this.emit('afterSaveMappings'); | ||
callback(err); | ||
}.bind(this)); | ||
} | ||
@@ -743,2 +804,4 @@ | ||
, _saveReferences: function(transaction, noReload, callback) { | ||
this.emit('beforeSaveRefernces'); | ||
async.each(this._changedReferences, function(key, next){ | ||
@@ -784,3 +847,6 @@ var value = this._references[key] | ||
} | ||
}.bind(this), callback); | ||
}.bind(this), function(err){ | ||
this.emit('afterSaveReferences'); | ||
callback(err); | ||
}.bind(this)); | ||
} | ||
@@ -787,0 +853,0 @@ |
@@ -40,3 +40,3 @@ !function(){ | ||
*/ | ||
, limit: function(limit) { | ||
, setLimit: function(limit) { | ||
if (type.number(limit)) this.limit = limit; | ||
@@ -50,3 +50,3 @@ else if (limit === null && this.limit) delete this.limit; | ||
*/ | ||
, offset: function(offset) { | ||
, setOffset: function(offset) { | ||
if (type.number(offset)) this.offset = offset; | ||
@@ -53,0 +53,0 @@ else if (offset === null && this.offset) delete this.offset; |
@@ -483,3 +483,3 @@ !function(){ | ||
, limit: function(limit) { | ||
this._resource.query.limit(limit); | ||
this._resource.query.setLimit(limit); | ||
return this; | ||
@@ -489,3 +489,3 @@ } | ||
, offset: function(offset) { | ||
this._resource.query.offset(offset); | ||
this._resource.query.setOffset(offset); | ||
return this; | ||
@@ -492,0 +492,0 @@ } |
{ | ||
"name" : "ee-orm" | ||
, "description" : "An easy to use ORM for node.js. Supports eager loading, complex queries, joins, transactions, complex database clusters & connection pooling." | ||
, "version" : "0.3.48" | ||
, "version" : "0.3.49" | ||
, "homepage" : "https://github.com/eventEmitter/ee-orm" | ||
@@ -6,0 +6,0 @@ , "author" : "Michael van der Weg <michael@eventemitter.com> (http://eventemitter.com/)" |
155
README.md
@@ -349,138 +349,43 @@ # ee-orm | ||
##### QueryBuilder inner workings | ||
##### Model Events | ||
1. Collect all joins, filters for the query, apply them | ||
2. Collect all subqueries (eager loading) if it or any child is selected | ||
3. Join its parent resource, all resources down to the root resource | ||
4. filter with the «in» statement | ||
5. Enjoy | ||
All events receive the following parameters (except those which contain the word «commit») | ||
- modelInstance: the model which emitted the event (this is passed to all models) | ||
- transaction: the transaction the current process is working on | ||
- callback: which must be called so the model can continue doing its actions. is the first parameter is set (err) then the model aborts the ucrrent process and rolls back the transaction. if the second parameter is set to true the model stops the curernt process and commits all changes. | ||
Eventlist | ||
- beforeSave: emitted before saving the model and all its references & mappings | ||
- afterSave: emitted when the model and all its references & mappings were saved, but the transaction was not yet commited | ||
- afterSaveCommit: emitted when the model and all its references & mappings were saved and the changes were commited | ||
#### Reserved Keywords (Outdated) | ||
- beforeUpdate: emitted before an upate | ||
- afterUpdate: emitted after the update without the transaction commited | ||
- afterUpdateCommit: emitted after the update with the changes were commited | ||
On the ORM itself the following keywords are reserved (your database should not have a name which is listed below): | ||
- beforeInsert: emitted before an insert | ||
- afterInsert: emitted after the insert without the transaction commited | ||
- afterInsertCommit: emitted after the insert with the changes were commited | ||
- $$$$_events | ||
- __proto__ | ||
- _initializeDatabases | ||
- _initializeOrm | ||
- _manageAccessorNames | ||
- _setProperty | ||
- addListener | ||
- emit | ||
- getDatabase | ||
- init | ||
- listener | ||
- off | ||
- on | ||
- once | ||
- prototype | ||
- hasOwnProperty | ||
- toString | ||
- toJSON | ||
the delete event gets as last parameter a flag which indicates if the record was / is goint to be deleted using a softdelete | ||
- beforeDelete: emitted before a delete | ||
- afterDeleteCommit: emitted after the delete was commited | ||
- beforeSaveReference: emitted before the referrences of the current model are saved | ||
- aftereSaveReferences: emitted after the references of the current model were saved, before the changes are commited | ||
- beforeSaveMappings: emitted before the mappings of the current model are saved | ||
- aftereSaveMappings: emitted after the mappings of the current model were saved, before the changes are commited | ||
On the Database level the following keywords are reserved (your database should not contain any tables using one of the names listed below): | ||
- beforeSaveBelongsTo: emitted before the belonging models of the current model are saved | ||
- aftereSaveBelongsTo: emitted after the belonging models of the current model were saved, before the changes are commited | ||
- $$$$_events | ||
- __proto__ | ||
- _delete | ||
- _getChangedValues | ||
- _getDatabase | ||
- _getFilters | ||
- _getOptions | ||
- _getSelect | ||
- _handleBelongsTo | ||
- _handleMapping | ||
- _handleReference | ||
- _initialize | ||
- _parseFilter | ||
- _parseSelect | ||
- _save | ||
- _saveBelongsTo | ||
- _saveChildren | ||
- _saveMappings | ||
- _saveReferences | ||
- _setChanged | ||
- _setProperty | ||
- _setValues | ||
- addListener | ||
- clone | ||
- createTransaction | ||
- delete | ||
- emit | ||
- executeQuery | ||
- filter | ||
- find | ||
- findOne | ||
- getDefinition | ||
- getEntityName | ||
- hasOwnProperty | ||
- init | ||
- isFromDatabase | ||
- isSaved | ||
- limit | ||
- listener | ||
- loadAll | ||
- off | ||
- offset | ||
- on | ||
- once | ||
- prototype | ||
- reload | ||
- save | ||
- toJSON | ||
- toString | ||
##### QueryBuilder inner workings | ||
On the Model level the following keywords are reserved (your tables should not contain any columns using on of the names listed below): | ||
- $$$$_events | ||
- __proto__ | ||
- _delete | ||
- _getChangedValues | ||
- _getFilters | ||
- _getOptions | ||
- _getSelect | ||
- _handleBelongsTo | ||
- _handleMapping | ||
- _handleReference | ||
- _parseFilter | ||
- _parseSelect | ||
- _save | ||
- _saveBelongsTo | ||
- _saveChildren | ||
- _saveMappings | ||
- _saveReferences | ||
- _setChanged | ||
- _setProperty | ||
- _setValues | ||
- addListener | ||
- clone | ||
- delete | ||
- emit | ||
- filter | ||
- find | ||
- findOne | ||
- getDefinition | ||
- getEntityName | ||
- hasOwnProperty | ||
- init | ||
- isFromDatabase | ||
- isQuery | ||
- isSaved | ||
- limit | ||
- listener | ||
- loadAll | ||
- off | ||
- offset | ||
- on | ||
- once | ||
- prototype | ||
- reload | ||
- save | ||
- toJSON | ||
- toString | ||
1. Collect all joins, filters for the query, apply them | ||
2. Collect all subqueries (eager loading) if it or any child is selected | ||
3. Join its parent resource, all resources down to the root resource | ||
4. filter with the «in» statement | ||
5. Enjoy |
22
test.js
@@ -26,8 +26,24 @@ | ||
var completed = 0, done = function(err) { log.warn('complete motherfucker'); | ||
if (err) return cb(err); | ||
if (++completed === 3){ log.wtf('starting to move, kiddy'); | ||
db.tree({name: 'child1.1'}).findOne(function(err, node){ | ||
if (err) cb(err); | ||
else if (!node) log.error('bnode not found!'); | ||
else { | ||
log.wtf('moving node'); | ||
node.setParentNode(db.tree({name: 'root'})); | ||
node.save(db); | ||
} | ||
}); | ||
} | ||
} | ||
new db.tree({name: 'root'}).setParentNode().save(function(err, node){ | ||
new db.tree({name: 'child1'}).setParentNode(node, null).save(function(err, node2){ | ||
new db.tree({name: 'child1.2'}).setParentNode(node2).save(cb); | ||
new db.tree({name: 'child1.1'}).setParentNode(node2).save(cb); | ||
new db.tree({name: 'child1.2'}).setParentNode(node2).save(done); | ||
new db.tree({name: 'child1.1'}).setParentNode(node2).save(done); | ||
}); | ||
new db.tree({name: 'child2'}).setParentNode(node).save(cb); | ||
new db.tree({name: 'child2'}).setParentNode(node).save(done); | ||
}); | ||
@@ -34,0 +50,0 @@ |
@@ -549,2 +549,24 @@ | ||
describe('[Limits & Offsets]', function() { | ||
it('the limit statement should work', function(done) { | ||
db.event(['*']).limit(2).find(function(err, events) { | ||
if (err) done(err); | ||
else { | ||
assert.equal(events.length, 2); | ||
done(); | ||
} | ||
}); | ||
}); | ||
it('the offset statement should work', function(done) { | ||
db.event(['*']).offset(3).find(function(err, events) { | ||
if (err) done(err); | ||
else { | ||
assert.equal(events.length, 1); | ||
done(); | ||
} | ||
}); | ||
}); | ||
}); | ||
describe('[Filtering]', function(){ | ||
@@ -551,0 +573,0 @@ it('Filter by a value', function(done){ |
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
233773
28
4368
391