Properly reset Memory connector cache on automigrate
This commit is contained in:
parent
8352ed3afc
commit
ad55681d69
|
@ -78,6 +78,11 @@ Memory.prototype.getCollection = function(model) {
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Memory.prototype.initCollection = function(model) {
|
||||||
|
this.collection(model, {});
|
||||||
|
this.collectionSeq(model, 1);
|
||||||
|
}
|
||||||
|
|
||||||
Memory.prototype.collection = function(model, val) {
|
Memory.prototype.collection = function(model, val) {
|
||||||
model = this.getCollection(model);
|
model = this.getCollection(model);
|
||||||
if (arguments.length > 1) this.cache[model] = val;
|
if (arguments.length > 1) this.cache[model] = val;
|
||||||
|
@ -181,10 +186,7 @@ Memory.prototype.saveToFile = function (result, callback) {
|
||||||
Memory.prototype.define = function defineModel(definition) {
|
Memory.prototype.define = function defineModel(definition) {
|
||||||
this.constructor.super_.prototype.define.apply(this, [].slice.call(arguments));
|
this.constructor.super_.prototype.define.apply(this, [].slice.call(arguments));
|
||||||
var m = definition.model.modelName;
|
var m = definition.model.modelName;
|
||||||
if(!this.collection(m)) {
|
if(!this.collection(m)) this.initCollection(m);
|
||||||
this.collection(m, {});
|
|
||||||
this.collectionSeq(m, 1);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Memory.prototype.create = function create(model, data, callback) {
|
Memory.prototype.create = function create(model, data, callback) {
|
||||||
|
@ -612,6 +614,16 @@ Memory.prototype.buildNearFilter = function (filter) {
|
||||||
// noop
|
// noop
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Memory.prototype.automigrate = function (models, cb) {
|
||||||
|
if (typeof models === 'function') cb = models, models = [];
|
||||||
|
if (models.length === 0) models = Object.keys(this._models);
|
||||||
|
var self = this;
|
||||||
|
models.forEach(function(m) {
|
||||||
|
self.initCollection(m);
|
||||||
|
});
|
||||||
|
if (cb) cb();
|
||||||
|
}
|
||||||
|
|
||||||
function merge(base, update) {
|
function merge(base, update) {
|
||||||
if (!base) {
|
if (!base) {
|
||||||
return update;
|
return update;
|
||||||
|
|
21
lib/dao.js
21
lib/dao.js
|
@ -79,7 +79,10 @@ DataAccessObject.applyProperties = function(data) {
|
||||||
};
|
};
|
||||||
|
|
||||||
DataAccessObject.applyScope = function(cond) {
|
DataAccessObject.applyScope = function(cond) {
|
||||||
|
var scope = this.definition.settings.scope;
|
||||||
|
if (typeof scope === 'object') {
|
||||||
|
mergeQuery(cond, scope || {}, this.definition.settings.scoping);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -330,17 +333,7 @@ DataAccessObject.exists = function exists(id, cb) {
|
||||||
*/
|
*/
|
||||||
DataAccessObject.findById = function find(id, cb) {
|
DataAccessObject.findById = function find(id, cb) {
|
||||||
if (stillConnecting(this.getDataSource(), this, arguments)) return;
|
if (stillConnecting(this.getDataSource(), this, arguments)) return;
|
||||||
|
this.findOne(byIdQuery(this, id), cb);
|
||||||
this.getDataSource().connector.find(this.modelName, id, function (err, data) {
|
|
||||||
var obj = null;
|
|
||||||
if (data) {
|
|
||||||
if (!getIdValue(this, data)) {
|
|
||||||
setIdValue(this, data, id);
|
|
||||||
}
|
|
||||||
obj = new this(data, {applySetters: false, persisted: true});
|
|
||||||
}
|
|
||||||
cb(err, obj);
|
|
||||||
}.bind(this));
|
|
||||||
};
|
};
|
||||||
|
|
||||||
DataAccessObject.findByIds = function(ids, cond, cb) {
|
DataAccessObject.findByIds = function(ids, cond, cb) {
|
||||||
|
@ -702,7 +695,7 @@ DataAccessObject.find = function find(query, cb) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
query = query || {};
|
query = query || {};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this._normalize(query);
|
this._normalize(query);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
@ -711,6 +704,8 @@ DataAccessObject.find = function find(query, cb) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.applyScope(query);
|
||||||
|
|
||||||
var near = query && geo.nearFilter(query.where);
|
var near = query && geo.nearFilter(query.where);
|
||||||
var supportsGeo = !!this.getDataSource().connector.buildNearFilter;
|
var supportsGeo = !!this.getDataSource().connector.buildNearFilter;
|
||||||
|
|
||||||
|
|
|
@ -134,7 +134,7 @@ ModelBaseClass.prototype._initProperties = function (data, options) {
|
||||||
}
|
}
|
||||||
if (properties[p]) {
|
if (properties[p]) {
|
||||||
// Managed property
|
// Managed property
|
||||||
if (applySetters) {
|
if (applySetters || properties[p].id) {
|
||||||
self[p] = propVal;
|
self[p] = propVal;
|
||||||
} else {
|
} else {
|
||||||
self.__data[p] = propVal;
|
self.__data[p] = propVal;
|
||||||
|
|
35
lib/utils.js
35
lib/utils.js
|
@ -56,14 +56,17 @@ function setScopeValuesFromWhere(data, where, targetModel) {
|
||||||
* Merge query parameters
|
* Merge query parameters
|
||||||
* @param {Object} base The base object to contain the merged results
|
* @param {Object} base The base object to contain the merged results
|
||||||
* @param {Object} update The object containing updates to be merged
|
* @param {Object} update The object containing updates to be merged
|
||||||
|
* @param {Object} spec Optionally specifies parameters to exclude (set to false)
|
||||||
* @returns {*|Object} The base object
|
* @returns {*|Object} The base object
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
function mergeQuery(base, update) {
|
function mergeQuery(base, update, spec) {
|
||||||
if (!update) {
|
if (!update) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
spec = spec || {};
|
||||||
base = base || {};
|
base = base || {};
|
||||||
|
|
||||||
if (update.where && Object.keys(update.where).length > 0) {
|
if (update.where && Object.keys(update.where).length > 0) {
|
||||||
if (base.where && Object.keys(base.where).length > 0) {
|
if (base.where && Object.keys(base.where).length > 0) {
|
||||||
base.where = {and: [base.where, update.where]};
|
base.where = {and: [base.where, update.where]};
|
||||||
|
@ -73,7 +76,7 @@ function mergeQuery(base, update) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Merge inclusion
|
// Merge inclusion
|
||||||
if (update.include) {
|
if (spec.include !== false && update.include) {
|
||||||
if (!base.include) {
|
if (!base.include) {
|
||||||
base.include = update.include;
|
base.include = update.include;
|
||||||
} else {
|
} else {
|
||||||
|
@ -82,30 +85,36 @@ function mergeQuery(base, update) {
|
||||||
base.include[update.include] = saved;
|
base.include[update.include] = saved;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (update.collect) {
|
|
||||||
|
if (spec.collect !== false && update.collect) {
|
||||||
base.collect = update.collect;
|
base.collect = update.collect;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Overwrite fields
|
||||||
|
if (spec.fields !== false && update.fields !== undefined) {
|
||||||
|
base.fields = update.fields;
|
||||||
|
}
|
||||||
|
|
||||||
// set order
|
// set order
|
||||||
if (!base.order && update.order) {
|
if ((!base.order || spec.order === false) && update.order) {
|
||||||
base.order = update.order;
|
base.order = update.order;
|
||||||
}
|
}
|
||||||
|
|
||||||
// overwrite pagination
|
// overwrite pagination
|
||||||
if (update.limit !== undefined) {
|
if (spec.limit !== false && update.limit !== undefined) {
|
||||||
base.limit = update.limit;
|
base.limit = update.limit;
|
||||||
}
|
}
|
||||||
if (update.skip !== undefined) {
|
|
||||||
|
var skip = spec.skip !== false && spec.offset !== false;
|
||||||
|
|
||||||
|
if (skip && update.skip !== undefined) {
|
||||||
base.skip = update.skip;
|
base.skip = update.skip;
|
||||||
}
|
}
|
||||||
if (update.offset !== undefined) {
|
|
||||||
|
if (skip && update.offset !== undefined) {
|
||||||
base.offset = update.offset;
|
base.offset = update.offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Overwrite fields
|
|
||||||
if (update.fields !== undefined) {
|
|
||||||
base.fields = update.fields;
|
|
||||||
}
|
|
||||||
return base;
|
return base;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,210 @@
|
||||||
|
// This test written in mocha+should.js
|
||||||
|
var should = require('./init.js');
|
||||||
|
var async = require('async');
|
||||||
|
|
||||||
|
var db, Product, Tool, Widget;
|
||||||
|
|
||||||
|
// This test requires a connector that can
|
||||||
|
// handle a custom collection or table name
|
||||||
|
|
||||||
|
describe('default scope', function () {
|
||||||
|
|
||||||
|
before(function (done) {
|
||||||
|
db = getSchema();
|
||||||
|
|
||||||
|
Product = db.define('Product', {
|
||||||
|
name: String,
|
||||||
|
kind: String,
|
||||||
|
description: String
|
||||||
|
}, {
|
||||||
|
scope: { order: 'name' },
|
||||||
|
});
|
||||||
|
|
||||||
|
Tool = db.define('Tool', {
|
||||||
|
name: String,
|
||||||
|
kind: String,
|
||||||
|
description: String
|
||||||
|
}, {
|
||||||
|
base: 'Product',
|
||||||
|
scope: { where: { kind: 'tool' }, order: 'name' },
|
||||||
|
mongodb: { collection: 'Product' },
|
||||||
|
memory: { collection: 'Product' }
|
||||||
|
});
|
||||||
|
|
||||||
|
Widget = db.define('Widget', {
|
||||||
|
name: String,
|
||||||
|
kind: String,
|
||||||
|
description: String
|
||||||
|
}, {
|
||||||
|
base: 'Product',
|
||||||
|
scope: { where: { kind: 'widget' }, order: 'name' },
|
||||||
|
mongodb: { collection: 'Product' },
|
||||||
|
memory: { collection: 'Product' }
|
||||||
|
});
|
||||||
|
|
||||||
|
db.automigrate(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('manipulation', function() {
|
||||||
|
|
||||||
|
var ids = {};
|
||||||
|
|
||||||
|
before(function(done) {
|
||||||
|
db.automigrate(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return a scoped instance', function() {
|
||||||
|
var p = new Tool({name: 'Product A', kind:'ignored'});
|
||||||
|
p.name.should.equal('Product A');
|
||||||
|
p.kind.should.equal('tool');
|
||||||
|
p.setAttributes({ kind: 'ignored' });
|
||||||
|
p.kind.should.equal('tool');
|
||||||
|
|
||||||
|
p.setAttribute('kind', 'other'); // currently not enforced
|
||||||
|
p.kind.should.equal('other');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create a scoped instance - tool', function(done) {
|
||||||
|
Tool.create({name: 'Product A', kind: 'ignored'}, function(err, p) {
|
||||||
|
should.not.exist(err);
|
||||||
|
p.name.should.equal('Product A');
|
||||||
|
p.kind.should.equal('tool');
|
||||||
|
ids.productA = p.id;
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create a scoped instance - widget', function(done) {
|
||||||
|
Widget.create({name: 'Product B', kind: 'ignored'}, function(err, p) {
|
||||||
|
should.not.exist(err);
|
||||||
|
p.name.should.equal('Product B');
|
||||||
|
p.kind.should.equal('widget');
|
||||||
|
ids.productB = p.id;
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should update a scoped instance - updateAttributes', function(done) {
|
||||||
|
Tool.findById(ids.productA, function(err, p) {
|
||||||
|
p.updateAttributes({description: 'A thing...', kind: 'ingored'}, function(err, inst) {
|
||||||
|
should.not.exist(err);
|
||||||
|
p.name.should.equal('Product A');
|
||||||
|
p.kind.should.equal('tool');
|
||||||
|
p.description.should.equal('A thing...');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should update a scoped instance - save', function(done) {
|
||||||
|
Tool.findById(ids.productA, function(err, p) {
|
||||||
|
p.description = 'Something...';
|
||||||
|
p.kind = 'ignored';
|
||||||
|
p.save(function(err, inst) {
|
||||||
|
should.not.exist(err);
|
||||||
|
p.name.should.equal('Product A');
|
||||||
|
p.kind.should.equal('tool');
|
||||||
|
p.description.should.equal('Something...');
|
||||||
|
Tool.findById(ids.productA, function(err, p) {
|
||||||
|
p.kind.should.equal('tool');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should update a scoped instance - updateOrCreate', function(done) {
|
||||||
|
var data = {id: ids.productA, description: 'Anything...', kind: 'ingored'};
|
||||||
|
Tool.updateOrCreate(data, function(err, p) {
|
||||||
|
should.not.exist(err);
|
||||||
|
p.name.should.equal('Product A');
|
||||||
|
p.kind.should.equal('tool');
|
||||||
|
p.description.should.equal('Anything...');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('queries', function() {
|
||||||
|
|
||||||
|
var ids = {};
|
||||||
|
|
||||||
|
before(function (done) {
|
||||||
|
db.automigrate(function(err) {
|
||||||
|
async.series([
|
||||||
|
function(next) {
|
||||||
|
Tool.create({name: 'Tool Z'}, function(err, inst) {
|
||||||
|
ids.toolZ = inst.id;
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
function(next) {
|
||||||
|
Widget.create({name: 'Widget Z'}, function(err, inst) {
|
||||||
|
ids.widgetZ = inst.id;
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
function(next) {
|
||||||
|
Tool.create({name: 'Tool A'}, function(err, inst) {
|
||||||
|
ids.toolA = inst.id;
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
function(next) {
|
||||||
|
Widget.create({name: 'Widget A'}, function(err, inst) {
|
||||||
|
ids.widgetA = inst.id;
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
], done);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should apply default scope - order', function(done) {
|
||||||
|
Product.find(function(err, products) {
|
||||||
|
should.not.exist(err);
|
||||||
|
products.should.have.length(4);
|
||||||
|
products[0].name.should.equal('Tool A');
|
||||||
|
products[1].name.should.equal('Tool Z');
|
||||||
|
products[2].name.should.equal('Widget A');
|
||||||
|
products[3].name.should.equal('Widget Z');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should apply default scope - order override', function(done) {
|
||||||
|
Product.find({ order: 'name DESC' }, function(err, products) {
|
||||||
|
should.not.exist(err);
|
||||||
|
products.should.have.length(4);
|
||||||
|
products[0].name.should.equal('Widget Z');
|
||||||
|
products[1].name.should.equal('Widget A');
|
||||||
|
products[2].name.should.equal('Tool Z');
|
||||||
|
products[3].name.should.equal('Tool A');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should apply default scope - where + order (tool)', function(done) {
|
||||||
|
Tool.find(function(err, products) {
|
||||||
|
should.not.exist(err);
|
||||||
|
products.should.have.length(2);
|
||||||
|
products[0].name.should.equal('Tool A');
|
||||||
|
products[1].name.should.equal('Tool Z');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should apply default scope - where + order (widget)', function(done) {
|
||||||
|
Widget.find({ order: 'name DESC' }, function(err, products) {
|
||||||
|
should.not.exist(err);
|
||||||
|
products.should.have.length(2);
|
||||||
|
products[0].name.should.equal('Widget Z');
|
||||||
|
products[1].name.should.equal('Widget A');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
|
@ -335,7 +335,7 @@ describe('relations', function () {
|
||||||
physician.patients.findById(id, function (err, ch) {
|
physician.patients.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.eql(id);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -387,7 +387,7 @@ describe('relations', function () {
|
||||||
physician.patients.findById(id, function (err, ch) {
|
physician.patients.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.eql(id);
|
||||||
ch.name.should.equal('aa');
|
ch.name.should.equal('aa');
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue