Conditionally pass options to connector CRUD methods
This commit is contained in:
parent
eb7c29826c
commit
5ef444e45d
|
@ -189,7 +189,7 @@ Memory.prototype.define = function defineModel(definition) {
|
||||||
if(!this.collection(m)) this.initCollection(m);
|
if(!this.collection(m)) this.initCollection(m);
|
||||||
};
|
};
|
||||||
|
|
||||||
Memory.prototype.create = function create(model, data, callback) {
|
Memory.prototype.create = function create(model, data, options, callback) {
|
||||||
// FIXME: [rfeng] We need to generate unique ids based on the id type
|
// FIXME: [rfeng] We need to generate unique ids based on the id type
|
||||||
// FIXME: [rfeng] We don't support composite ids yet
|
// FIXME: [rfeng] We don't support composite ids yet
|
||||||
var currentId = this.collectionSeq(model);
|
var currentId = this.collectionSeq(model);
|
||||||
|
@ -221,15 +221,15 @@ Memory.prototype.create = function create(model, data, callback) {
|
||||||
this.saveToFile(id, callback);
|
this.saveToFile(id, callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
Memory.prototype.updateOrCreate = function (model, data, callback) {
|
Memory.prototype.updateOrCreate = function (model, data, options, callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
this.exists(model, self.getIdValue(model, data), function (err, exists) {
|
this.exists(model, self.getIdValue(model, data), options, function (err, exists) {
|
||||||
if (exists) {
|
if (exists) {
|
||||||
self.save(model, data, function(err, data) {
|
self.save(model, data, options, function(err, data) {
|
||||||
callback(err, data, { isNewInstance: false });
|
callback(err, data, { isNewInstance: false });
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
self.create(model, data, function (err, id) {
|
self.create(model, data, options, function (err, id) {
|
||||||
self.setIdValue(model, data, id);
|
self.setIdValue(model, data, id);
|
||||||
callback(err, data, { isNewInstance: true });
|
callback(err, data, { isNewInstance: true });
|
||||||
});
|
});
|
||||||
|
@ -237,7 +237,7 @@ Memory.prototype.updateOrCreate = function (model, data, callback) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
Memory.prototype.save = function save(model, data, callback) {
|
Memory.prototype.save = function save(model, data, options, callback) {
|
||||||
var id = this.getIdValue(model, data);
|
var id = this.getIdValue(model, data);
|
||||||
var cachedModels = this.collection(model);
|
var cachedModels = this.collection(model);
|
||||||
var modelData = cachedModels && this.collection(model)[id];
|
var modelData = cachedModels && this.collection(model)[id];
|
||||||
|
@ -251,19 +251,19 @@ Memory.prototype.save = function save(model, data, callback) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
Memory.prototype.exists = function exists(model, id, callback) {
|
Memory.prototype.exists = function exists(model, id, options, callback) {
|
||||||
process.nextTick(function () {
|
process.nextTick(function () {
|
||||||
callback(null, this.collection(model) && this.collection(model).hasOwnProperty(id));
|
callback(null, this.collection(model) && this.collection(model).hasOwnProperty(id));
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
};
|
};
|
||||||
|
|
||||||
Memory.prototype.find = function find(model, id, callback) {
|
Memory.prototype.find = function find(model, id, options, callback) {
|
||||||
process.nextTick(function () {
|
process.nextTick(function () {
|
||||||
callback(null, id in this.collection(model) && this.fromDb(model, this.collection(model)[id]));
|
callback(null, id in this.collection(model) && this.fromDb(model, this.collection(model)[id]));
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
};
|
};
|
||||||
|
|
||||||
Memory.prototype.destroy = function destroy(model, id, callback) {
|
Memory.prototype.destroy = function destroy(model, id, options, callback) {
|
||||||
delete this.collection(model)[id];
|
delete this.collection(model)[id];
|
||||||
this.saveToFile(null, callback);
|
this.saveToFile(null, callback);
|
||||||
};
|
};
|
||||||
|
@ -310,7 +310,7 @@ function getValue(obj, path) {
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
Memory.prototype.all = function all(model, filter, callback) {
|
Memory.prototype.all = function all(model, filter, options, callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var nodes = Object.keys(this.collection(model)).map(function (key) {
|
var nodes = Object.keys(this.collection(model)).map(function (key) {
|
||||||
return this.fromDb(model, this.collection(model)[key]);
|
return this.fromDb(model, this.collection(model)[key]);
|
||||||
|
@ -559,11 +559,7 @@ function applyFilter(filter) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Memory.prototype.destroyAll = function destroyAll(model, where, callback) {
|
Memory.prototype.destroyAll = function destroyAll(model, where, options, callback) {
|
||||||
if (!callback && 'function' === typeof where) {
|
|
||||||
callback = where;
|
|
||||||
where = undefined;
|
|
||||||
}
|
|
||||||
var cache = this.collection(model);
|
var cache = this.collection(model);
|
||||||
var filter = null;
|
var filter = null;
|
||||||
var count = 0;
|
var count = 0;
|
||||||
|
@ -582,7 +578,7 @@ Memory.prototype.destroyAll = function destroyAll(model, where, callback) {
|
||||||
this.saveToFile({ count: count }, callback);
|
this.saveToFile({ count: count }, callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
Memory.prototype.count = function count(model, callback, where) {
|
Memory.prototype.count = function count(model, where, options, callback) {
|
||||||
var cache = this.collection(model);
|
var cache = this.collection(model);
|
||||||
var data = Object.keys(cache);
|
var data = Object.keys(cache);
|
||||||
if (where) {
|
if (where) {
|
||||||
|
@ -598,7 +594,7 @@ Memory.prototype.count = function count(model, callback, where) {
|
||||||
};
|
};
|
||||||
|
|
||||||
Memory.prototype.update =
|
Memory.prototype.update =
|
||||||
Memory.prototype.updateAll = function updateAll(model, where, data, cb) {
|
Memory.prototype.updateAll = function updateAll(model, where, data, options, cb) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var cache = this.collection(model);
|
var cache = this.collection(model);
|
||||||
var filter = null;
|
var filter = null;
|
||||||
|
@ -614,7 +610,7 @@ Memory.prototype.update =
|
||||||
// The id value from the cache is string
|
// The id value from the cache is string
|
||||||
// Get the real id from the inst
|
// Get the real id from the inst
|
||||||
id = self.getIdValue(model, inst);
|
id = self.getIdValue(model, inst);
|
||||||
self.updateAttributes(model, id, data, done);
|
self.updateAttributes(model, id, data, options, done);
|
||||||
} else {
|
} else {
|
||||||
process.nextTick(done);
|
process.nextTick(done);
|
||||||
}
|
}
|
||||||
|
@ -624,7 +620,7 @@ Memory.prototype.update =
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
Memory.prototype.updateAttributes = function updateAttributes(model, id, data, cb) {
|
Memory.prototype.updateAttributes = function updateAttributes(model, id, data, options, cb) {
|
||||||
if (!id) {
|
if (!id) {
|
||||||
var err = new Error('You must provide an id when updating attributes!');
|
var err = new Error('You must provide an id when updating attributes!');
|
||||||
if (cb) {
|
if (cb) {
|
||||||
|
@ -643,7 +639,7 @@ Memory.prototype.updateAttributes = function updateAttributes(model, id, data, c
|
||||||
var modelData = cachedModels && this.collection(model)[id];
|
var modelData = cachedModels && this.collection(model)[id];
|
||||||
|
|
||||||
if (modelData) {
|
if (modelData) {
|
||||||
this.save(model, data, cb);
|
this.save(model, data, options, cb);
|
||||||
} else {
|
} else {
|
||||||
cb(new Error('Could not update attributes. Object with id ' + id + ' does not exist!'));
|
cb(new Error('Could not update attributes. Object with id ' + id + ' does not exist!'));
|
||||||
}
|
}
|
||||||
|
|
253
lib/dao.js
253
lib/dao.js
|
@ -124,6 +124,14 @@ DataAccessObject.lookupModel = function(data) {
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the connector instance for the given model class
|
||||||
|
* @returns {Connector} The connector instance
|
||||||
|
*/
|
||||||
|
DataAccessObject.getConnector = function() {
|
||||||
|
return this.getDataSource().connector;
|
||||||
|
}
|
||||||
|
|
||||||
// Empty callback function
|
// Empty callback function
|
||||||
function noCallback(err, result) {
|
function noCallback(err, result) {
|
||||||
// NOOP
|
// NOOP
|
||||||
|
@ -154,6 +162,10 @@ DataAccessObject.create = function (data, options, cb) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var Model = this;
|
var Model = this;
|
||||||
|
var connector = Model.getConnector();
|
||||||
|
assert(typeof connector.create === 'function',
|
||||||
|
'create() must be implemented by the connector');
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
if (options === undefined && cb === undefined) {
|
if (options === undefined && cb === undefined) {
|
||||||
|
@ -260,7 +272,7 @@ DataAccessObject.create = function (data, options, cb) {
|
||||||
var _idName = idName(Model);
|
var _idName = idName(Model);
|
||||||
var modelName = Model.modelName;
|
var modelName = Model.modelName;
|
||||||
var val = removeUndefined(obj.toObject(true));
|
var val = removeUndefined(obj.toObject(true));
|
||||||
this._adapter().create(modelName, this.constructor._forDB(val), function (err, id, rev) {
|
function createCallback(err, id, rev) {
|
||||||
if (id) {
|
if (id) {
|
||||||
obj.__data[_idName] = id;
|
obj.__data[_idName] = id;
|
||||||
defineReadonlyProp(obj, _idName, id);
|
defineReadonlyProp(obj, _idName, id);
|
||||||
|
@ -290,7 +302,13 @@ DataAccessObject.create = function (data, options, cb) {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}, obj);
|
}
|
||||||
|
|
||||||
|
if (connector.create.length === 4) {
|
||||||
|
connector.create(modelName, this.constructor._forDB(val), options, createCallback);
|
||||||
|
} else {
|
||||||
|
connector.create(modelName, this.constructor._forDB(val), createCallback);
|
||||||
|
}
|
||||||
}, obj, cb);
|
}, obj, cb);
|
||||||
}, obj, cb);
|
}, obj, cb);
|
||||||
}
|
}
|
||||||
|
@ -363,6 +381,7 @@ DataAccessObject.updateOrCreate = DataAccessObject.upsert = function upsert(data
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
var Model = this;
|
var Model = this;
|
||||||
|
var connector = Model.getConnector();
|
||||||
|
|
||||||
var id = getIdValue(this, data);
|
var id = getIdValue(this, data);
|
||||||
if (id === undefined || id === null) {
|
if (id === undefined || id === null) {
|
||||||
|
@ -381,7 +400,7 @@ DataAccessObject.updateOrCreate = DataAccessObject.upsert = function upsert(data
|
||||||
if (err) return cb(err);
|
if (err) return cb(err);
|
||||||
|
|
||||||
var isOriginalQuery = isWhereByGivenId(Model, ctx.query.where, id)
|
var isOriginalQuery = isWhereByGivenId(Model, ctx.query.where, id)
|
||||||
if (Model.getDataSource().connector.updateOrCreate && isOriginalQuery) {
|
if (connector.updateOrCreate && isOriginalQuery) {
|
||||||
var context = {
|
var context = {
|
||||||
Model: Model,
|
Model: Model,
|
||||||
where: ctx.query.where,
|
where: ctx.query.where,
|
||||||
|
@ -403,10 +422,15 @@ DataAccessObject.updateOrCreate = DataAccessObject.upsert = function upsert(data
|
||||||
Model.applyProperties(update, inst);
|
Model.applyProperties(update, inst);
|
||||||
Model = Model.lookupModel(update);
|
Model = Model.lookupModel(update);
|
||||||
|
|
||||||
|
var connector = self.getConnector();
|
||||||
|
|
||||||
if (Model.settings.validateUpsert === false) {
|
if (Model.settings.validateUpsert === false) {
|
||||||
update = removeUndefined(update);
|
update = removeUndefined(update);
|
||||||
self.getDataSource().connector
|
if (connector.updateOrCreate.length === 4) {
|
||||||
.updateOrCreate(Model.modelName, update, done);
|
connector.updateOrCreate(Model.modelName, update, options, done);
|
||||||
|
} else {
|
||||||
|
connector.updateOrCreate(Model.modelName, update, done);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
inst.isValid(function(valid) {
|
inst.isValid(function(valid) {
|
||||||
if (!valid) {
|
if (!valid) {
|
||||||
|
@ -421,8 +445,11 @@ DataAccessObject.updateOrCreate = DataAccessObject.upsert = function upsert(data
|
||||||
}
|
}
|
||||||
|
|
||||||
update = removeUndefined(update);
|
update = removeUndefined(update);
|
||||||
self.getDataSource().connector
|
if (connector.updateOrCreate.length === 4) {
|
||||||
.updateOrCreate(Model.modelName, update, done);
|
connector.updateOrCreate(Model.modelName, update, options, done);
|
||||||
|
} else {
|
||||||
|
connector.updateOrCreate(Model.modelName, update, done);
|
||||||
|
}
|
||||||
}, update);
|
}, update);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -533,47 +560,52 @@ DataAccessObject.findOrCreate = function findOrCreate(query, data, options, cb)
|
||||||
|
|
||||||
var Model = this;
|
var Model = this;
|
||||||
var self = this;
|
var self = this;
|
||||||
|
var connector = Model.getConnector();
|
||||||
|
|
||||||
function _findOrCreate(query, data) {
|
function _findOrCreate(query, data) {
|
||||||
var modelName = self.modelName;
|
var modelName = self.modelName;
|
||||||
data = removeUndefined(data);
|
data = removeUndefined(data);
|
||||||
self.getDataSource().connector.findOrCreate(modelName, query,
|
function findOrCreateCallback(err, data, created) {
|
||||||
self._forDB(data),
|
var obj, Model = self.lookupModel(data);
|
||||||
function(err, data, created) {
|
|
||||||
var obj, Model = self.lookupModel(data);
|
|
||||||
|
|
||||||
if (data) {
|
if (data) {
|
||||||
obj = new Model(data, {fields: query.fields, applySetters: false,
|
obj = new Model(data, {fields: query.fields, applySetters: false,
|
||||||
persisted: true});
|
persisted: true});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (created) {
|
if (created) {
|
||||||
var context = {
|
var context = {
|
||||||
Model: Model,
|
Model: Model,
|
||||||
instance: obj,
|
instance: obj,
|
||||||
isNewInstance: true,
|
isNewInstance: true,
|
||||||
hookState: hookState,
|
hookState: hookState,
|
||||||
options: options
|
options: options
|
||||||
};
|
};
|
||||||
Model.notifyObserversOf('after save', context, function(err) {
|
Model.notifyObserversOf('after save', context, function(err) {
|
||||||
if (cb.promise) {
|
|
||||||
cb(err, [obj, created]);
|
|
||||||
} else {
|
|
||||||
cb(err, obj, created);
|
|
||||||
}
|
|
||||||
if (!err) Model.emit('changed', obj);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
if (cb.promise) {
|
if (cb.promise) {
|
||||||
cb(err, [obj, created]);
|
cb(err, [obj, created]);
|
||||||
} else {
|
} else {
|
||||||
cb(err, obj, created);
|
cb(err, obj, created);
|
||||||
}
|
}
|
||||||
|
if (!err) Model.emit('changed', obj);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
if (cb.promise) {
|
||||||
|
cb(err, [obj, created]);
|
||||||
|
} else {
|
||||||
|
cb(err, obj, created);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (connector.findOrCreate.length === 5) {
|
||||||
|
connector.findOrCreate(modelName, query, self._forDB(data), options, findOrCreateCallback);
|
||||||
|
} else {
|
||||||
|
connector.findOrCreate(modelName, query, self._forDB(data), findOrCreateCallback);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.getDataSource().connector.findOrCreate) {
|
if (connector.findOrCreate) {
|
||||||
query.limit = 1;
|
query.limit = 1;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -707,7 +739,7 @@ DataAccessObject.exists = function exists(id, options, cb) {
|
||||||
* @param {Object} [options] Options
|
* @param {Object} [options] Options
|
||||||
* @param {Function} cb Callback called with (err, instance)
|
* @param {Function} cb Callback called with (err, instance)
|
||||||
*/
|
*/
|
||||||
DataAccessObject.findById = function find(id, filter, options, cb) {
|
DataAccessObject.findById = function findById(id, filter, options, cb) {
|
||||||
var connectionPromise = stillConnecting(this.getDataSource(), this, arguments);
|
var connectionPromise = stillConnecting(this.getDataSource(), this, arguments);
|
||||||
if (connectionPromise) {
|
if (connectionPromise) {
|
||||||
return connectionPromise;
|
return connectionPromise;
|
||||||
|
@ -1179,6 +1211,10 @@ DataAccessObject.find = function find(query, options, cb) {
|
||||||
|
|
||||||
var hookState = {};
|
var hookState = {};
|
||||||
var self = this;
|
var self = this;
|
||||||
|
var connector = self.getConnector();
|
||||||
|
|
||||||
|
assert(typeof connector.all === 'function',
|
||||||
|
'all() must be implemented by the connector');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this._normalize(query);
|
this._normalize(query);
|
||||||
|
@ -1192,12 +1228,12 @@ DataAccessObject.find = function find(query, options, cb) {
|
||||||
this.applyScope(query);
|
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 = !!connector.buildNearFilter;
|
||||||
|
|
||||||
if (near) {
|
if (near) {
|
||||||
if (supportsGeo) {
|
if (supportsGeo) {
|
||||||
// convert it
|
// convert it
|
||||||
this.getDataSource().connector.buildNearFilter(query, near);
|
connector.buildNearFilter(query, near);
|
||||||
} else if (query.where) {
|
} else if (query.where) {
|
||||||
// do in memory query
|
// do in memory query
|
||||||
// using all documents
|
// using all documents
|
||||||
|
@ -1212,7 +1248,7 @@ DataAccessObject.find = function find(query, options, cb) {
|
||||||
self.notifyObserversOf('access', context, function(err, ctx) {
|
self.notifyObserversOf('access', context, function(err, ctx) {
|
||||||
if (err) return cb(err);
|
if (err) return cb(err);
|
||||||
|
|
||||||
self.getDataSource().connector.all(self.modelName, {}, function (err, data) {
|
function geoCallback(err, data) {
|
||||||
var memory = new Memory();
|
var memory = new Memory();
|
||||||
var modelName = self.modelName;
|
var modelName = self.modelName;
|
||||||
|
|
||||||
|
@ -1225,18 +1261,24 @@ DataAccessObject.find = function find(query, options, cb) {
|
||||||
model: self
|
model: self
|
||||||
});
|
});
|
||||||
|
|
||||||
data.forEach(function (obj) {
|
data.forEach(function(obj) {
|
||||||
memory.create(modelName, obj, function () {
|
memory.create(modelName, obj, options, function() {
|
||||||
// noop
|
// noop
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// FIXME: apply "includes" and other transforms - see allCb below
|
// FIXME: apply "includes" and other transforms - see allCb below
|
||||||
memory.all(modelName, ctx.query, cb);
|
memory.all(modelName, ctx.query, options, cb);
|
||||||
} else {
|
} else {
|
||||||
cb(null, []);
|
cb(null, []);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
|
if (connector.all.length === 4) {
|
||||||
|
connector.all(self.modelName, {}, options, geoCallback);
|
||||||
|
} else {
|
||||||
|
connector.all(self.modelName, {}, geoCallback);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// already handled
|
// already handled
|
||||||
|
@ -1301,7 +1343,11 @@ DataAccessObject.find = function find(query, options, cb) {
|
||||||
};
|
};
|
||||||
|
|
||||||
if (options.notify === false) {
|
if (options.notify === false) {
|
||||||
self.getDataSource().connector.all(self.modelName, query, allCb);
|
if (connector.all.length === 4) {
|
||||||
|
connector.all(self.modelName, query, options, allCb);
|
||||||
|
} else {
|
||||||
|
connector.all(self.modelName, query, allCb);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
var context = {
|
var context = {
|
||||||
Model: this,
|
Model: this,
|
||||||
|
@ -1312,7 +1358,11 @@ DataAccessObject.find = function find(query, options, cb) {
|
||||||
this.notifyObserversOf('access', context, function(err, ctx) {
|
this.notifyObserversOf('access', context, function(err, ctx) {
|
||||||
if (err) return cb(err);
|
if (err) return cb(err);
|
||||||
var query = ctx.query;
|
var query = ctx.query;
|
||||||
self.getDataSource().connector.all(self.modelName, query, allCb);
|
if (connector.all.length === 4) {
|
||||||
|
connector.all(self.modelName, query, options, allCb);
|
||||||
|
} else {
|
||||||
|
connector.all(self.modelName, query, allCb);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return cb.promise;
|
return cb.promise;
|
||||||
|
@ -1381,6 +1431,10 @@ DataAccessObject.remove = DataAccessObject.deleteAll = DataAccessObject.destroyA
|
||||||
}
|
}
|
||||||
|
|
||||||
var Model = this;
|
var Model = this;
|
||||||
|
var connector = Model.getConnector();
|
||||||
|
|
||||||
|
assert(typeof connector.destroyAll === 'function',
|
||||||
|
'destroyAll() must be implemented by the connector');
|
||||||
|
|
||||||
if (options === undefined && cb === undefined) {
|
if (options === undefined && cb === undefined) {
|
||||||
if (typeof where === 'function') {
|
if (typeof where === 'function') {
|
||||||
|
@ -1442,7 +1496,11 @@ DataAccessObject.remove = DataAccessObject.deleteAll = DataAccessObject.destroyA
|
||||||
|
|
||||||
function doDelete(where) {
|
function doDelete(where) {
|
||||||
if (whereIsEmpty(where)) {
|
if (whereIsEmpty(where)) {
|
||||||
Model.getDataSource().connector.destroyAll(Model.modelName, done);
|
if (connector.destroyAll.length === 4) {
|
||||||
|
connector.destroyAll(Model.modelName, {}, options, done);
|
||||||
|
} else {
|
||||||
|
connector.destroyAll(Model.modelName, {}, done);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
// Support an optional where object
|
// Support an optional where object
|
||||||
|
@ -1454,7 +1512,11 @@ DataAccessObject.remove = DataAccessObject.deleteAll = DataAccessObject.destroyA
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Model.getDataSource().connector.destroyAll(Model.modelName, where, done);
|
if (connector.destroyAll.length === 4) {
|
||||||
|
connector.destroyAll(Model.modelName, where, options, done);
|
||||||
|
} else {
|
||||||
|
connector.destroyAll(Model.modelName, where, done);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1577,6 +1639,13 @@ DataAccessObject.count = function (where, options, cb) {
|
||||||
assert(typeof options === 'object', 'The options argument must be an object');
|
assert(typeof options === 'object', 'The options argument must be an object');
|
||||||
assert(typeof cb === 'function', 'The cb argument must be a function');
|
assert(typeof cb === 'function', 'The cb argument must be a function');
|
||||||
|
|
||||||
|
var Model = this;
|
||||||
|
var connector = Model.getConnector();
|
||||||
|
assert(typeof connector.count === 'function',
|
||||||
|
'count() must be implemented by the connector');
|
||||||
|
assert(connector.count.length >= 3,
|
||||||
|
'count() must take at least 3 arguments');
|
||||||
|
|
||||||
var hookState = {};
|
var hookState = {};
|
||||||
|
|
||||||
var query = { where: where };
|
var query = { where: where };
|
||||||
|
@ -1593,8 +1662,6 @@ DataAccessObject.count = function (where, options, cb) {
|
||||||
return cb.promise;
|
return cb.promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
var Model = this;
|
|
||||||
|
|
||||||
var context = {
|
var context = {
|
||||||
Model: Model,
|
Model: Model,
|
||||||
query: { where: where },
|
query: { where: where },
|
||||||
|
@ -1602,10 +1669,19 @@ DataAccessObject.count = function (where, options, cb) {
|
||||||
options: options
|
options: options
|
||||||
};
|
};
|
||||||
this.notifyObserversOf('access', context, function(err, ctx) {
|
this.notifyObserversOf('access', context, function(err, ctx) {
|
||||||
if (err) return cb(err);
|
if (err) return cb(err);
|
||||||
where = ctx.query.where;
|
where = ctx.query.where;
|
||||||
Model.getDataSource().connector.count(Model.modelName, cb, where);
|
|
||||||
});
|
if (connector.count.length <= 3) {
|
||||||
|
// Old signature, please note where is the last
|
||||||
|
// count(model, cb, where)
|
||||||
|
connector.count(Model.modelName, cb, where);
|
||||||
|
} else {
|
||||||
|
// New signature
|
||||||
|
// count(model, where, options, cb)
|
||||||
|
connector.count(Model.modelName, where, options, cb);
|
||||||
|
}
|
||||||
|
});
|
||||||
return cb.promise;
|
return cb.promise;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1649,6 +1725,7 @@ DataAccessObject.prototype.save = function (options, cb) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var inst = this;
|
var inst = this;
|
||||||
|
var connector = inst.getConnector();
|
||||||
var modelName = Model.modelName;
|
var modelName = Model.modelName;
|
||||||
|
|
||||||
var context = {
|
var context = {
|
||||||
|
@ -1687,7 +1764,7 @@ DataAccessObject.prototype.save = function (options, cb) {
|
||||||
inst.trigger('save', function (saveDone) {
|
inst.trigger('save', function (saveDone) {
|
||||||
inst.trigger('update', function (updateDone) {
|
inst.trigger('update', function (updateDone) {
|
||||||
data = removeUndefined(data);
|
data = removeUndefined(data);
|
||||||
inst._adapter().save(modelName, inst.constructor._forDB(data), function (err, unusedData, result) {
|
function saveCallback(err, unusedData, result) {
|
||||||
if (err) {
|
if (err) {
|
||||||
return cb(err, inst);
|
return cb(err, inst);
|
||||||
}
|
}
|
||||||
|
@ -1710,7 +1787,13 @@ DataAccessObject.prototype.save = function (options, cb) {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
|
|
||||||
|
if (connector.save.length === 4) {
|
||||||
|
connector.save(modelName, inst.constructor._forDB(data), options, saveCallback);
|
||||||
|
} else {
|
||||||
|
connector.save(modelName, inst.constructor._forDB(data), saveCallback);
|
||||||
|
}
|
||||||
}, data, cb);
|
}, data, cb);
|
||||||
}, data, cb);
|
}, data, cb);
|
||||||
}
|
}
|
||||||
|
@ -1775,6 +1858,11 @@ DataAccessObject.updateAll = function (where, data, options, cb) {
|
||||||
assert(typeof options === 'object', 'The options argument must be an object');
|
assert(typeof options === 'object', 'The options argument must be an object');
|
||||||
assert(typeof cb === 'function', 'The cb argument must be a function');
|
assert(typeof cb === 'function', 'The cb argument must be a function');
|
||||||
|
|
||||||
|
var Model = this;
|
||||||
|
var connector = Model.getDataSource().connector;
|
||||||
|
assert(typeof connector.update === 'function',
|
||||||
|
'update() must be implemented by the connector');
|
||||||
|
|
||||||
var hookState = {};
|
var hookState = {};
|
||||||
|
|
||||||
var query = { where: where };
|
var query = { where: where };
|
||||||
|
@ -1783,8 +1871,6 @@ DataAccessObject.updateAll = function (where, data, options, cb) {
|
||||||
|
|
||||||
where = query.where;
|
where = query.where;
|
||||||
|
|
||||||
var Model = this;
|
|
||||||
|
|
||||||
var context = {
|
var context = {
|
||||||
Model: Model,
|
Model: Model,
|
||||||
query: { where: where },
|
query: { where: where },
|
||||||
|
@ -1807,7 +1893,6 @@ DataAccessObject.updateAll = function (where, data, options, cb) {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
function doUpdate(where, data) {
|
function doUpdate(where, data) {
|
||||||
try {
|
try {
|
||||||
where = removeUndefined(where);
|
where = removeUndefined(where);
|
||||||
|
@ -1820,8 +1905,7 @@ DataAccessObject.updateAll = function (where, data, options, cb) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
var connector = Model.getDataSource().connector;
|
function updateCallback(err, info) {
|
||||||
connector.update(Model.modelName, where, data, function(err, info) {
|
|
||||||
if (err) return cb (err);
|
if (err) return cb (err);
|
||||||
var context = {
|
var context = {
|
||||||
Model: Model,
|
Model: Model,
|
||||||
|
@ -1831,9 +1915,15 @@ DataAccessObject.updateAll = function (where, data, options, cb) {
|
||||||
options: options
|
options: options
|
||||||
};
|
};
|
||||||
Model.notifyObserversOf('after save', context, function(err, ctx) {
|
Model.notifyObserversOf('after save', context, function(err, ctx) {
|
||||||
return cb(err, info);
|
return cb(err, info);
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
|
|
||||||
|
if (connector.update.length === 5) {
|
||||||
|
connector.update(Model.modelName, where, data, options, updateCallback);
|
||||||
|
} else {
|
||||||
|
connector.update(Model.modelName, where, data, updateCallback);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return cb.promise;
|
return cb.promise;
|
||||||
};
|
};
|
||||||
|
@ -1846,7 +1936,7 @@ DataAccessObject.prototype.isNewRecord = function () {
|
||||||
* Return connector of current record
|
* Return connector of current record
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
DataAccessObject.prototype._adapter = function () {
|
DataAccessObject.prototype.getConnector = function () {
|
||||||
return this.getDataSource().connector;
|
return this.getDataSource().connector;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1877,11 +1967,12 @@ DataAccessObject.prototype.remove =
|
||||||
assert(typeof options === 'object', 'The options argument should be an object');
|
assert(typeof options === 'object', 'The options argument should be an object');
|
||||||
assert(typeof cb === 'function', 'The cb argument should be a function');
|
assert(typeof cb === 'function', 'The cb argument should be a function');
|
||||||
|
|
||||||
var hookState = {};
|
|
||||||
|
|
||||||
var inst = this;
|
var inst = this;
|
||||||
|
var connector = this.getConnector();
|
||||||
|
|
||||||
var Model = this.constructor;
|
var Model = this.constructor;
|
||||||
var id = getIdValue(this.constructor, this);
|
var id = getIdValue(this.constructor, this);
|
||||||
|
var hookState = {};
|
||||||
|
|
||||||
var context = {
|
var context = {
|
||||||
Model: Model,
|
Model: Model,
|
||||||
|
@ -1928,12 +2019,12 @@ DataAccessObject.prototype.remove =
|
||||||
}
|
}
|
||||||
|
|
||||||
inst.trigger('destroy', function (destroyed) {
|
inst.trigger('destroy', function (destroyed) {
|
||||||
inst._adapter().destroy(inst.constructor.modelName, id, function (err) {
|
function destroyCallback(err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
return cb(err);
|
return cb(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
destroyed(function () {
|
destroyed(function() {
|
||||||
var context = {
|
var context = {
|
||||||
Model: Model,
|
Model: Model,
|
||||||
where: where,
|
where: where,
|
||||||
|
@ -1946,7 +2037,13 @@ DataAccessObject.prototype.remove =
|
||||||
if (!err) Model.emit('deleted', id);
|
if (!err) Model.emit('deleted', id);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
|
|
||||||
|
if (connector.destroy.length === 4) {
|
||||||
|
connector.destroy(inst.constructor.modelName, id, options, destroyCallback);
|
||||||
|
} else {
|
||||||
|
connector.destroy(inst.constructor.modelName, id, destroyCallback);
|
||||||
|
}
|
||||||
}, null, cb);
|
}, null, cb);
|
||||||
}
|
}
|
||||||
return cb.promise;
|
return cb.promise;
|
||||||
|
@ -2066,11 +2163,14 @@ DataAccessObject.prototype.updateAttributes = function updateAttributes(data, op
|
||||||
assert(typeof options === 'object', 'The options argument must be an object');
|
assert(typeof options === 'object', 'The options argument must be an object');
|
||||||
assert(typeof cb === 'function', 'The cb argument must be a function');
|
assert(typeof cb === 'function', 'The cb argument must be a function');
|
||||||
|
|
||||||
var hookState = {};
|
|
||||||
|
|
||||||
var inst = this;
|
var inst = this;
|
||||||
var Model = this.constructor;
|
var Model = this.constructor;
|
||||||
|
var connector = inst.getConnector();
|
||||||
|
assert(typeof connector.updateAttributes === 'function',
|
||||||
|
'updateAttributes() must be implemented by the connector');
|
||||||
|
|
||||||
var model = Model.modelName;
|
var model = Model.modelName;
|
||||||
|
var hookState = {};
|
||||||
|
|
||||||
// Convert the data to be plain object so that update won't be confused
|
// Convert the data to be plain object so that update won't be confused
|
||||||
if (data instanceof Model) {
|
if (data instanceof Model) {
|
||||||
|
@ -2129,8 +2229,7 @@ DataAccessObject.prototype.updateAttributes = function updateAttributes(data, op
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inst._adapter().updateAttributes(model, getIdValue(inst.constructor, inst),
|
function updateAttributesCallback(err) {
|
||||||
inst.constructor._forDB(typedData), function (err) {
|
|
||||||
if (!err) inst.__persisted = true;
|
if (!err) inst.__persisted = true;
|
||||||
done.call(inst, function () {
|
done.call(inst, function () {
|
||||||
saveDone.call(inst, function () {
|
saveDone.call(inst, function () {
|
||||||
|
@ -2148,7 +2247,15 @@ DataAccessObject.prototype.updateAttributes = function updateAttributes(data, op
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
|
|
||||||
|
if (connector.updateAttributes.length === 5) {
|
||||||
|
connector.updateAttributes(model, getIdValue(inst.constructor, inst),
|
||||||
|
inst.constructor._forDB(typedData), options, updateAttributesCallback);
|
||||||
|
} else {
|
||||||
|
connector.updateAttributes(model, getIdValue(inst.constructor, inst),
|
||||||
|
inst.constructor._forDB(typedData), updateAttributesCallback);
|
||||||
|
}
|
||||||
}, data, cb);
|
}, data, cb);
|
||||||
}, data, cb);
|
}, data, cb);
|
||||||
}, data);
|
}, data);
|
||||||
|
|
|
@ -136,11 +136,17 @@ describe('datatypes', function () {
|
||||||
function testDataInDB(done) {
|
function testDataInDB(done) {
|
||||||
|
|
||||||
// verify that the value stored in the db is still an object
|
// verify that the value stored in the db is still an object
|
||||||
db.connector.find(Model.modelName, id, function (err, data) {
|
function cb(err, data) {
|
||||||
should.exist(data);
|
should.exist(data);
|
||||||
data.num.should.be.type('number');
|
data.num.should.be.type('number');
|
||||||
done();
|
done();
|
||||||
});
|
}
|
||||||
|
|
||||||
|
if (db.connector.find.length === 4) {
|
||||||
|
db.connector.find(Model.modelName, id, {}, cb);
|
||||||
|
} else {
|
||||||
|
db.connector.find(Model.modelName, id, cb);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -252,16 +258,27 @@ describe('datatypes', function () {
|
||||||
created.should.have.properties(EXPECTED);
|
created.should.have.properties(EXPECTED);
|
||||||
saved.should.have.properties(EXPECTED);
|
saved.should.have.properties(EXPECTED);
|
||||||
|
|
||||||
TestModel.dataSource.connector.all(
|
function cb(err, found) {
|
||||||
TestModel.modelName,
|
if (err) return done(err);
|
||||||
{ where: { id: created.id } },
|
should.exist(found[0]);
|
||||||
function(err, found) {
|
found[0].should.have.properties(EXPECTED);
|
||||||
if (err) return done(err);
|
done();
|
||||||
should.exist(found[0]);
|
}
|
||||||
found[0].should.have.properties(EXPECTED);
|
|
||||||
done();
|
if (TestModel.dataSource.connector.all.length === 4) {
|
||||||
}
|
TestModel.dataSource.connector.all(
|
||||||
);
|
TestModel.modelName,
|
||||||
|
{where: {id: created.id}},
|
||||||
|
{},
|
||||||
|
cb
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
TestModel.dataSource.connector.all(
|
||||||
|
TestModel.modelName,
|
||||||
|
{where: {id: created.id}},
|
||||||
|
cb
|
||||||
|
);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -238,7 +238,7 @@ describe('Memory connector', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should successfully extract 1 user (Lennon) from the db', function(done) {
|
it('should successfully extract 1 user (Lennon) from the db', function(done) {
|
||||||
User.find({where: {birthday: {between: [new Date(1970,0),new Date(1990,0)]}}},
|
User.find({where: {birthday: {between: [new Date(1970,0),new Date(1990,0)]}}},
|
||||||
function(err, users) {
|
function(err, users) {
|
||||||
should(users.length).be.equal(1);
|
should(users.length).be.equal(1);
|
||||||
should(users[0].name).be.equal('John Lennon');
|
should(users[0].name).be.equal('John Lennon');
|
||||||
|
@ -247,7 +247,7 @@ describe('Memory connector', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should successfully extract 2 users from the db', function(done) {
|
it('should successfully extract 2 users from the db', function(done) {
|
||||||
User.find({where: {birthday: {between: [new Date(1940,0),new Date(1990,0)]}}},
|
User.find({where: {birthday: {between: [new Date(1940,0),new Date(1990,0)]}}},
|
||||||
function(err, users) {
|
function(err, users) {
|
||||||
should(users.length).be.equal(2);
|
should(users.length).be.equal(2);
|
||||||
done();
|
done();
|
||||||
|
@ -255,7 +255,7 @@ describe('Memory connector', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should successfully extract 0 user from the db', function(done) {
|
it('should successfully extract 0 user from the db', function(done) {
|
||||||
User.find({where: {birthday: {between: [new Date(1990,0), Date.now()]}}},
|
User.find({where: {birthday: {between: [new Date(1990,0), Date.now()]}}},
|
||||||
function(err, users) {
|
function(err, users) {
|
||||||
should(users.length).be.equal(0);
|
should(users.length).be.equal(0);
|
||||||
done();
|
done();
|
||||||
|
@ -489,9 +489,9 @@ describe('Optimized connector', function() {
|
||||||
|
|
||||||
// optimized methods
|
// optimized methods
|
||||||
ds.connector.findOrCreate = function (model, query, data, callback) {
|
ds.connector.findOrCreate = function (model, query, data, callback) {
|
||||||
this.all(model, query, function (err, list) {
|
this.all(model, query, {}, function (err, list) {
|
||||||
if (err || (list && list[0])) return callback(err, list && list[0], false);
|
if (err || (list && list[0])) return callback(err, list && list[0], false);
|
||||||
this.create(model, data, function (err) {
|
this.create(model, data, {}, function (err) {
|
||||||
callback(err, data, true);
|
callback(err, data, true);
|
||||||
});
|
});
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
|
@ -509,5 +509,79 @@ describe('Unoptimized connector', function() {
|
||||||
require('./persistence-hooks.suite')(ds, should);
|
require('./persistence-hooks.suite')(ds, should);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('Memory connector with options', function() {
|
||||||
|
var ds, savedOptions = {}, Post;
|
||||||
|
|
||||||
|
before(function() {
|
||||||
|
ds = new DataSource({connector: 'memory'});
|
||||||
|
ds.connector.create = function(model, data, options, cb) {
|
||||||
|
savedOptions.create = options;
|
||||||
|
process.nextTick(function() {
|
||||||
|
cb(null, 1);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
ds.connector.update = function(model, where, data, options, cb) {
|
||||||
|
savedOptions.update = options;
|
||||||
|
process.nextTick(function() {
|
||||||
|
cb(null, {count: 1});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
ds.connector.all = function(model, filter, options, cb) {
|
||||||
|
savedOptions.find = options;
|
||||||
|
process.nextTick(function() {
|
||||||
|
cb(null, [{title: 't1', content: 'c1'}]);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
Post = ds.define('Post', {
|
||||||
|
title: String,
|
||||||
|
content: String
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should receive options from the find method', function(done) {
|
||||||
|
var opts = {transaction: 'tx1'};
|
||||||
|
Post.find({where: {title: 't1'}}, opts, function(err, p) {
|
||||||
|
savedOptions.find.should.be.eql(opts);
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should receive options from the find method', function(done) {
|
||||||
|
var opts = {transaction: 'tx2'};
|
||||||
|
Post.find({}, opts, function(err, p) {
|
||||||
|
savedOptions.find.should.be.eql(opts);
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should treat first object arg as filter for find', function(done) {
|
||||||
|
var filter = {title: 't1'};
|
||||||
|
Post.find(filter, function(err, p) {
|
||||||
|
savedOptions.find.should.be.eql({});
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should receive options from the create method', function(done) {
|
||||||
|
var opts = {transaction: 'tx3'};
|
||||||
|
Post.create({title: 't1', content: 'c1'}, opts, function(err, p) {
|
||||||
|
savedOptions.create.should.be.eql(opts);
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should receive options from the update method', function(done) {
|
||||||
|
var opts = {transaction: 'tx4'};
|
||||||
|
Post.update({title: 't1'}, {content: 'c1 --> c2'},
|
||||||
|
opts, function(err, p) {
|
||||||
|
savedOptions.update.should.be.eql(opts);
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue