Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Query middleware support #10

Open
wants to merge 9 commits into
base: develop
Choose a base branch
from
58 changes: 54 additions & 4 deletions lib/sequence.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ Sequence = function(schema, options) {
Sequence.getInstance = function(schema, options) {
var sequence = new Sequence(schema, options),
id = sequence.getId();

if(sequenceArchive.existsSequence(id)){
throw new Error('Counter already defined for field "'+id+'"');
}
Expand Down Expand Up @@ -119,7 +119,6 @@ Sequence.prototype._getCounterReferenceField = function(doc) {
reference.push(JSON.stringify(doc[this._options.reference_fields[i]]));
}
}

return reference;
};

Expand Down Expand Up @@ -180,6 +179,8 @@ Sequence.prototype._createCounterModel = function() {
* @method _setHooks
*/
Sequence.prototype._setHooks = function() {
var _this = this;

this._schema.pre('save', true, (function(sequence){
return function(next, done) {
var doc = this;
Expand All @@ -194,6 +195,52 @@ Sequence.prototype._setHooks = function() {
}.bind(doc));
};
})(this));

this._schema.pre('findOneAndUpdate', function(next) {
// jscs:disable
var _thisquery = this,
referenceValue;

// jscs:enable

this.model.findOne(_thisquery._conditions, function(err, obj) {
if (err) return next();
if (obj) return next();
else {
referenceValue = _this._getCounterReferenceField(_thisquery._update);
_this._setNextCounterByReference(_this.getId(), referenceValue, function(err, seq) {
if (err) return next();
_thisquery._update['$setOnInsert'] = _thisquery._update['$setOnInsert'] || {};
_thisquery._update['$setOnInsert'][_this._options.inc_field] = seq;
next();
});
}
});
});


this._schema.pre('update', function(next, done) {
// jscs:disable
var _thisquery = this,
referenceValue;

// jscs:enable


this.model.findOne(_thisquery._conditions, function(err, obj) {
if (err) return next();
if (obj) return next();
else {
referenceValue = _this._getCounterReferenceField(_thisquery._update.$set);
_this._setNextCounterByReference(_this.getId(), referenceValue, function(err, seq) {
if (err) return next();
_thisquery._update['$setOnInsert'] = _thisquery._update['$setOnInsert'] || {};
_thisquery._update['$setOnInsert'][_this._options.inc_field] = seq;
next();
});
}
});
});
};

/**
Expand All @@ -215,7 +262,6 @@ Sequence.prototype._setMethods = function() {
if (_.isNull(sequence)) {
return callback(new Error('Trying to increment a wrong sequence using the id ' + id));
}
// sequence = sequence.sequence;

sequence._setNextCounter(this, function(err, seq) {
if (err) return callback(err);
Expand All @@ -235,7 +281,11 @@ Sequence.prototype._setMethods = function() {
*/
Sequence.prototype._setNextCounter = function(doc, callback) {
var id = this.getId();
var referenceValue = this._getCounterReferenceField(doc);
var referenceValue = this._getCounterReferenceField(doc);
this._setNextCounterByReference(id, referenceValue, callback);
};

Sequence.prototype._setNextCounterByReference = function(id, referenceValue, callback) {
this._counterModel.findOneAndUpdate(
{ id: id, reference_value: referenceValue },
{ $inc: { seq: 1 } },
Expand Down
154 changes: 152 additions & 2 deletions test/base.js
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,156 @@ describe('Basic => ', function() {

});

describe('hook', function(){
describe('simple counters', function(){
before(function(done) {
var SimpleFieldSchema = new Schema({
id: Number,
val: String,
tag: String
});
var wrapper = function(schema, options) {
var instance = AutoIncrement(schema, options);
this.setNextCounterSpy = sinon.spy(instance, '_setNextCounterByReference');
return instance;
}.bind(this);
SimpleFieldSchema.plugin(wrapper, {id: 'id_hook_test', inc_field: 'id'});
this.SimpleField = mongoose.model('SimpleFieldHookTest', SimpleFieldSchema);
this.SimpleField.create({val: 'existing'}, function(err){
this.setNextCounterSpy.reset();
done(err);
}.bind(this));
});

afterEach(function(){
this.setNextCounterSpy.reset();
});

it('is called when saving a new document', function(done){
var t = new this.SimpleField({val: 'a'});
t.save(function(err){
sinon.assert.calledOnce(this.setNextCounterSpy);
done(err);
}.bind(this));
});

it('is not called when saving an existing document', function(done){
var t = new this.SimpleField({val: 'a'});
t.isNew = false;
t.save(function(err){
sinon.assert.notCalled(this.setNextCounterSpy);
done(err);
}.bind(this));
});

it('is called when upserting in an update and result in an insert', function(done){
this.SimpleField.update({val: '1234'}, {tag: 'nothing'}, {upsert: true}, function(err, doc){
sinon.assert.calledOnce(this.setNextCounterSpy);
done(err);
}.bind(this));
});

it('is not called when upserting in an update and not result in an insert', function(done){
this.SimpleField.update({val: 'existing'}, {tag: 'update'}, {upsert: true}, function(err, doc){
sinon.assert.notCalled(this.setNextCounterSpy);
done(err);
}.bind(this));
});

it('is called when upserting in an findOneAndUpdate and result in an insert', function(done){
this.SimpleField.findOneAndUpdate({val: '4567'}, {tag: 'nothing'}, {upsert: true}, function(err, doc){
sinon.assert.calledOnce(this.setNextCounterSpy);
done(err);
}.bind(this));
});

it('is not called when upserting in an findOneAndUpdate and not result in an insert', function(done){
this.SimpleField.findOneAndUpdate({val: '1234'}, {tag: 'findOneAndUpdate'}, {upsert: true}, function(err, doc){
sinon.assert.notCalled(this.setNextCounterSpy);
done(err);
}.bind(this));
});
});

describe('referenced counters', function() {
before(function(done) {
var SimpleFieldSchema = new Schema({
same_tag_members: Number,
val: String,
tag: String
});
var wrapper = function(schema, options) {
var instance = AutoIncrement(schema, options);
this.instance = instance;
this.setNextCounterSpy = sinon.spy(instance, '_setNextCounterByReference');
return instance;
}.bind(this);
SimpleFieldSchema.plugin(wrapper, {
id: 'id_hook_test_referenced',
inc_field: 'same_tag_members',
reference_fields: ['tag']}
);
this.SimpleField = mongoose.model('SimpleFieldHookTestReferenced', SimpleFieldSchema);
this.SimpleField.create({val: 'existing'}, function(err){
this.setNextCounterSpy.reset();
done(err);
}.bind(this));
});

afterEach(function(){
this.setNextCounterSpy.reset();
});

it('are called when saving a new document', function(done){
var t = new this.SimpleField({val: 'a', tag: 'red'});
t.save(function(err){
sinon.assert.calledWith(
this.setNextCounterSpy,
'id_hook_test_referenced',
this.instance._getCounterReferenceField(t)
);
done(err);
}.bind(this));
});

it('are called when upserting in an update and result in an insert', function(done){
this.SimpleField.update({val: '1234'}, {tag: 'blue'}, {upsert: true}, function(err, doc){
sinon.assert.calledWith(
this.setNextCounterSpy,
'id_hook_test_referenced',
this.instance._getCounterReferenceField({tag:'blue'})
);
done(err);
}.bind(this));
});

it('are not called when upserting in an update and not result in an insert', function(done){
this.SimpleField.update({val: 'existing'}, {tag: 'green'}, {upsert: true}, function(err, doc){
sinon.assert.notCalled(this.setNextCounterSpy);
done(err);
}.bind(this));
});

it('are called when upserting in an findOneAndUpdate and result in an insert', function(done){
this.SimpleField.findOneAndUpdate({val: '4567'}, {tag: 'pink'}, {upsert: true}, function(err, doc){
sinon.assert.calledWith(
this.setNextCounterSpy,
'id_hook_test_referenced',
this.instance._getCounterReferenceField({tag:'pink'})
);
done(err);
}.bind(this));
});

it('are not called when upserting in an findOneAndUpdate and not result in an insert', function(done){
this.SimpleField.findOneAndUpdate({val: '1234'}, {tag: 'yellow'}, {upsert: true}, function(err, doc){
sinon.assert.notCalled(this.setNextCounterSpy);
done(err);
}.bind(this));
});
});
});

describe('a manual increment field => ', function() {

before(function(done) {
Expand Down Expand Up @@ -342,7 +492,7 @@ describe('Basic => ', function() {
assert.throws(function(){
UnusedSchema.plugin(AutoIncrement, {inc_field: 'inhabitant', reference_fields: ['country', 'city'], disable_hooks: true});
}, Error);

});
});

Expand Down Expand Up @@ -427,7 +577,7 @@ describe('Basic => ', function() {
});
});
});
});
});

});
});