added include functionnality to abstract class and mysql
This commit is contained in:
parent
24ccb0ffc2
commit
c6bddf170a
|
@ -58,6 +58,10 @@ AbstractClass.prototype._initProperties = function (data, applySetters) {
|
||||||
value: {}
|
value: {}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (data['__cachedRelations']) {
|
||||||
|
this.__cachedRelations = data['__cachedRelations'];
|
||||||
|
}
|
||||||
|
|
||||||
for (var i in data) this.__data[i] = this.__dataWas[i] = data[i];
|
for (var i in data) this.__data[i] = this.__dataWas[i] = data[i];
|
||||||
|
|
||||||
if (applySetters && ctor.setter) {
|
if (applySetters && ctor.setter) {
|
||||||
|
@ -384,6 +388,202 @@ AbstractClass.count = function (where, cb) {
|
||||||
this.schema.adapter.count(this.modelName, cb, where);
|
this.schema.adapter.count(this.modelName, cb, where);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param objects
|
||||||
|
* @param include
|
||||||
|
*/
|
||||||
|
AbstractClass.include = function (objects, include, callback, preprocessDataCallback) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
if ((include.constructor.name == 'Array' && include.length == 0) || (include.constructor.name == 'Object' && Object.keys(include).length == 0)) {
|
||||||
|
callback(null, objects);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('******************* OLD INCLUDE', include);
|
||||||
|
include = processIncludeJoin(include);
|
||||||
|
console.log('******************* NEW INCLUDE', include);
|
||||||
|
|
||||||
|
var keyVals = {};
|
||||||
|
var objsByKeys = {};
|
||||||
|
|
||||||
|
var nbCallbacks = 0;
|
||||||
|
for (var i = 0; i < include.length; i++) {
|
||||||
|
var cb = processIncludeItem(objects, include[i], keyVals, objsByKeys);
|
||||||
|
if (cb !== null) {
|
||||||
|
nbCallbacks++;
|
||||||
|
cb(function() {
|
||||||
|
nbCallbacks--;
|
||||||
|
if (nbCallbacks == 0) {
|
||||||
|
callback(null, objects);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
async.parallel(callbacks, function(err, results) {
|
||||||
|
callback(null, objs);
|
||||||
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
|
function processIncludeJoin(ij) {
|
||||||
|
if (typeof ij === 'string') {
|
||||||
|
ij = [ij];
|
||||||
|
}
|
||||||
|
if (ij.constructor.name === 'Object') {
|
||||||
|
var newIj = [];
|
||||||
|
for (var key in ij) {
|
||||||
|
var obj = {};
|
||||||
|
obj[key] = ij[key];
|
||||||
|
newIj.push(obj);
|
||||||
|
}
|
||||||
|
return newIj;
|
||||||
|
}
|
||||||
|
return ij;
|
||||||
|
}
|
||||||
|
|
||||||
|
function processIncludeItem(objs, include, keyVals, objsByKeys) {
|
||||||
|
var relations = self.relations;
|
||||||
|
|
||||||
|
if (include.constructor.name === 'Object') {
|
||||||
|
var relationName = Object.keys(include)[0];
|
||||||
|
var subInclude = include[relationName];
|
||||||
|
} else {
|
||||||
|
var relationName = include;
|
||||||
|
var subInclude = [];
|
||||||
|
}
|
||||||
|
var relation = relations[relationName];
|
||||||
|
|
||||||
|
var req = {'where': {}};
|
||||||
|
var keysToBeProcessed = {};
|
||||||
|
if (!keyVals[relation.keyFrom]) {
|
||||||
|
objsByKeys[relation.keyFrom] = {};
|
||||||
|
for (var j = 0; j < objs.length; j++) {
|
||||||
|
keysToBeProcessed[objs[j][relation.keyFrom]] = true;
|
||||||
|
if (!objsByKeys[relation.keyFrom][objs[j][relation.keyFrom]]) {
|
||||||
|
objsByKeys[relation.keyFrom][objs[j][relation.keyFrom]] = [];
|
||||||
|
}
|
||||||
|
objsByKeys[relation.keyFrom][objs[j][relation.keyFrom]].push(objs[j]);
|
||||||
|
}
|
||||||
|
keyVals[relation.keyFrom] = Object.keys(objsByKeys[relation.keyFrom]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keyVals[relation.keyFrom].length > 0) {
|
||||||
|
// deep clone is necessary since inq seems to change the processed array
|
||||||
|
var inValues = [];
|
||||||
|
for (var j = 0; j < keyVals[relation.keyFrom].length; j++) {
|
||||||
|
if (keyVals[relation.keyFrom][j] !== 'null') {
|
||||||
|
inValues.push(keyVals[relation.keyFrom][j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
req['where'][relation.keyTo] = {inq: inValues};
|
||||||
|
req['include'] = subInclude;
|
||||||
|
|
||||||
|
return function(cb) {
|
||||||
|
relation.modelTo.all(req, function(err, dataIncluded) {
|
||||||
|
var objsIncluded = preprocessDataCallback(relation.modelTo.modelName, dataIncluded);
|
||||||
|
for (var i = 0; i < objsIncluded.length; i++) {
|
||||||
|
delete keysToBeProcessed[objsIncluded[i][relation.keyTo]];
|
||||||
|
var objectsFrom = objsByKeys[relation.keyFrom][objsIncluded[i][relation.keyTo]];
|
||||||
|
for (var j = 0; j < objectsFrom.length; j++) {
|
||||||
|
if (!objectsFrom[j].__cachedRelations) {
|
||||||
|
objectsFrom[j].__cachedRelations = {};
|
||||||
|
}
|
||||||
|
if (relation.multiple) {
|
||||||
|
if (!objectsFrom[j].__cachedRelations[relationName]) {
|
||||||
|
objectsFrom[j].__cachedRelations[relationName] = [];
|
||||||
|
}
|
||||||
|
objectsFrom[j].__cachedRelations[relationName].push(objsIncluded[i]);
|
||||||
|
} else {
|
||||||
|
objectsFrom[j].__cachedRelations[relationName] = objsIncluded[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// No relation have been found for these keys
|
||||||
|
for (var key in keysToBeProcessed) {
|
||||||
|
var objectsFrom = objsByKeys[relation.keyFrom][key];
|
||||||
|
for (var j = 0; j < objectsFrom.length; j++) {
|
||||||
|
if (!objectsFrom[j].__cachedRelations) {
|
||||||
|
objectsFrom[j].__cachedRelations = {};
|
||||||
|
}
|
||||||
|
objectsFrom[j].__cachedRelations[relationName] = relation.multiple ? [] : null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cb(err, objsIncluded);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
function processIncludeItem(model, objs, include, keyVals, objsByKeys) {
|
||||||
|
var relations = model.relations;
|
||||||
|
|
||||||
|
if (include.constructor.name === 'Object') {
|
||||||
|
var relationName = Object.keys(include)[0];
|
||||||
|
var relation = relations[relationName];
|
||||||
|
var subInclude = include[relationName];
|
||||||
|
} else {
|
||||||
|
var relationName = include;
|
||||||
|
var relation = relations[relationName];
|
||||||
|
var subInclude = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
var req = {'where': {}};
|
||||||
|
if (!keyVals[relation.keyFrom]) {
|
||||||
|
objsByKeys[relation.keyFrom] = {};
|
||||||
|
for (var j = 0; j < objs.length; j++) {
|
||||||
|
if (!objsByKeys[relation.keyFrom][objs[j][relation.keyFrom]]) {
|
||||||
|
objsByKeys[relation.keyFrom][objs[j][relation.keyFrom]] = [];
|
||||||
|
}
|
||||||
|
objsByKeys[relation.keyFrom][objs[j][relation.keyFrom]].push(objs[j]);
|
||||||
|
}
|
||||||
|
keyVals[relation.keyFrom] = Object.keys(objsByKeys[relation.keyFrom]);
|
||||||
|
}
|
||||||
|
req['where'][relation.keyTo] = {inq: keyVals[relation.keyFrom]};
|
||||||
|
req['include'] = subInclude;
|
||||||
|
return function(cb) {
|
||||||
|
relation.model.all(req, function(err, dataIncluded) {
|
||||||
|
|
||||||
|
var objsIncluded = dataIncluded.map(function (obj) {
|
||||||
|
return self.fromDatabase(relation.model.modelName, obj);
|
||||||
|
});
|
||||||
|
|
||||||
|
for (var i = 0; i < objsIncluded.length; i++) {
|
||||||
|
var objectsFrom = objsByKeys[relation.keyFrom][objsIncluded[i][relation.keyTo]];
|
||||||
|
for (var j = 0; j < objectsFrom.length; j++) {
|
||||||
|
if (!objectsFrom[j].__cache) {
|
||||||
|
objectsFrom[j].__cache = {};
|
||||||
|
}
|
||||||
|
if (relation.type == 'hasMany') {
|
||||||
|
if (!objectsFrom[j].__cache[relationName]) {
|
||||||
|
objectsFrom[j].__cache[relationName] = [];
|
||||||
|
}
|
||||||
|
objectsFrom[j].__cache[relationName].push(objsIncluded[i]);
|
||||||
|
} else {
|
||||||
|
objectsFrom[j].__cache[relationName] = objsIncluded[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cb(err, dataIncluded);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return string representation of class
|
* Return string representation of class
|
||||||
*
|
*
|
||||||
|
@ -671,6 +871,7 @@ AbstractClass.hasMany = function hasMany(anotherClass, params) {
|
||||||
type: 'hasMany',
|
type: 'hasMany',
|
||||||
keyFrom: 'id',
|
keyFrom: 'id',
|
||||||
keyTo: params['foreignKey'],
|
keyTo: params['foreignKey'],
|
||||||
|
modelTo: anotherClass,
|
||||||
multiple: true
|
multiple: true
|
||||||
};
|
};
|
||||||
// each instance of this class should have method named
|
// each instance of this class should have method named
|
||||||
|
@ -744,6 +945,7 @@ AbstractClass.belongsTo = function (anotherClass, params) {
|
||||||
type: 'belongsTo',
|
type: 'belongsTo',
|
||||||
keyFrom: params['foreignKey'],
|
keyFrom: params['foreignKey'],
|
||||||
keyTo: 'id',
|
keyTo: 'id',
|
||||||
|
modelTo: anotherClass,
|
||||||
multiple: false
|
multiple: false
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -751,6 +953,10 @@ AbstractClass.belongsTo = function (anotherClass, params) {
|
||||||
this.prototype['__finders__'] = this.prototype['__finders__'] || {};
|
this.prototype['__finders__'] = this.prototype['__finders__'] || {};
|
||||||
|
|
||||||
this.prototype['__finders__'][methodName] = function (id, cb) {
|
this.prototype['__finders__'][methodName] = function (id, cb) {
|
||||||
|
if (id === null) {
|
||||||
|
cb(null, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
anotherClass.find(id, function (err,inst) {
|
anotherClass.find(id, function (err,inst) {
|
||||||
if (err) return cb(err);
|
if (err) return cb(err);
|
||||||
if (!inst) return cb(null, null);
|
if (!inst) return cb(null, null);
|
||||||
|
|
|
@ -224,9 +224,20 @@ MySQL.prototype.all = function all(model, filter, callback) {
|
||||||
if (err) {
|
if (err) {
|
||||||
return callback(err, []);
|
return callback(err, []);
|
||||||
}
|
}
|
||||||
callback(null, data.map(function (obj) {
|
var preprocessDataCallback = function(model, data) {
|
||||||
|
data.map(function (obj) {
|
||||||
return self.fromDatabase(model, obj);
|
return self.fromDatabase(model, obj);
|
||||||
}));
|
});
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
var objs = preprocessDataCallback(model, data);
|
||||||
|
if (filter && filter.include) {
|
||||||
|
this._models[model].model.include(objs, filter.include, callback, preprocessDataCallback);
|
||||||
|
} else {
|
||||||
|
callback(null, objs);
|
||||||
|
}
|
||||||
|
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
|
|
||||||
return sql;
|
return sql;
|
||||||
|
|
Loading…
Reference in New Issue