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;
|
||||
}
|
||||
|
||||
Memory.prototype.initCollection = function(model) {
|
||||
this.collection(model, {});
|
||||
this.collectionSeq(model, 1);
|
||||
}
|
||||
|
||||
Memory.prototype.collection = function(model, val) {
|
||||
model = this.getCollection(model);
|
||||
if (arguments.length > 1) this.cache[model] = val;
|
||||
|
@ -181,10 +186,7 @@ Memory.prototype.saveToFile = function (result, callback) {
|
|||
Memory.prototype.define = function defineModel(definition) {
|
||||
this.constructor.super_.prototype.define.apply(this, [].slice.call(arguments));
|
||||
var m = definition.model.modelName;
|
||||
if(!this.collection(m)) {
|
||||
this.collection(m, {});
|
||||
this.collectionSeq(m, 1);
|
||||
}
|
||||
if(!this.collection(m)) this.initCollection(m);
|
||||
};
|
||||
|
||||
Memory.prototype.create = function create(model, data, callback) {
|
||||
|
@ -612,6 +614,16 @@ Memory.prototype.buildNearFilter = function (filter) {
|
|||
// 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) {
|
||||
if (!base) {
|
||||
return update;
|
||||
|
|
21
lib/dao.js
21
lib/dao.js
|
@ -79,7 +79,10 @@ DataAccessObject.applyProperties = function(data) {
|
|||
};
|
||||
|
||||
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) {
|
||||
if (stillConnecting(this.getDataSource(), this, arguments)) return;
|
||||
|
||||
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));
|
||||
this.findOne(byIdQuery(this, id), cb);
|
||||
};
|
||||
|
||||
DataAccessObject.findByIds = function(ids, cond, cb) {
|
||||
|
@ -702,7 +695,7 @@ DataAccessObject.find = function find(query, cb) {
|
|||
var self = this;
|
||||
|
||||
query = query || {};
|
||||
|
||||
|
||||
try {
|
||||
this._normalize(query);
|
||||
} catch (err) {
|
||||
|
@ -711,6 +704,8 @@ DataAccessObject.find = function find(query, cb) {
|
|||
});
|
||||
}
|
||||
|
||||
this.applyScope(query);
|
||||
|
||||
var near = query && geo.nearFilter(query.where);
|
||||
var supportsGeo = !!this.getDataSource().connector.buildNearFilter;
|
||||
|
||||
|
|
|
@ -134,7 +134,7 @@ ModelBaseClass.prototype._initProperties = function (data, options) {
|
|||
}
|
||||
if (properties[p]) {
|
||||
// Managed property
|
||||
if (applySetters) {
|
||||
if (applySetters || properties[p].id) {
|
||||
self[p] = propVal;
|
||||
} else {
|
||||
self.__data[p] = propVal;
|
||||
|
|
35
lib/utils.js
35
lib/utils.js
|
@ -56,14 +56,17 @@ function setScopeValuesFromWhere(data, where, targetModel) {
|
|||
* Merge query parameters
|
||||
* @param {Object} base The base object to contain the merged results
|
||||
* @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
|
||||
* @private
|
||||
*/
|
||||
function mergeQuery(base, update) {
|
||||
function mergeQuery(base, update, spec) {
|
||||
if (!update) {
|
||||
return;
|
||||
}
|
||||
spec = spec || {};
|
||||
base = base || {};
|
||||
|
||||
if (update.where && Object.keys(update.where).length > 0) {
|
||||
if (base.where && Object.keys(base.where).length > 0) {
|
||||
base.where = {and: [base.where, update.where]};
|
||||
|
@ -73,7 +76,7 @@ function mergeQuery(base, update) {
|
|||
}
|
||||
|
||||
// Merge inclusion
|
||||
if (update.include) {
|
||||
if (spec.include !== false && update.include) {
|
||||
if (!base.include) {
|
||||
base.include = update.include;
|
||||
} else {
|
||||
|
@ -82,30 +85,36 @@ function mergeQuery(base, update) {
|
|||
base.include[update.include] = saved;
|
||||
}
|
||||
}
|
||||
if (update.collect) {
|
||||
|
||||
if (spec.collect !== false && update.collect) {
|
||||
base.collect = update.collect;
|
||||
}
|
||||
|
||||
|
||||
// Overwrite fields
|
||||
if (spec.fields !== false && update.fields !== undefined) {
|
||||
base.fields = update.fields;
|
||||
}
|
||||
|
||||
// set order
|
||||
if (!base.order && update.order) {
|
||||
if ((!base.order || spec.order === false) && update.order) {
|
||||
base.order = update.order;
|
||||
}
|
||||
|
||||
// overwrite pagination
|
||||
if (update.limit !== undefined) {
|
||||
if (spec.limit !== false && update.limit !== undefined) {
|
||||
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;
|
||||
}
|
||||
if (update.offset !== undefined) {
|
||||
|
||||
if (skip && update.offset !== undefined) {
|
||||
base.offset = update.offset;
|
||||
}
|
||||
|
||||
// Overwrite fields
|
||||
if (update.fields !== undefined) {
|
||||
base.fields = update.fields;
|
||||
}
|
||||
|
||||
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) {
|
||||
should.not.exist(err);
|
||||
should.exist(ch);
|
||||
ch.id.should.equal(id);
|
||||
ch.id.should.eql(id);
|
||||
done();
|
||||
});
|
||||
}
|
||||
|
@ -387,7 +387,7 @@ describe('relations', function () {
|
|||
physician.patients.findById(id, function (err, ch) {
|
||||
should.not.exist(err);
|
||||
should.exist(ch);
|
||||
ch.id.should.equal(id);
|
||||
ch.id.should.eql(id);
|
||||
ch.name.should.equal('aa');
|
||||
done();
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue