diff --git a/lib/scope.js b/lib/scope.js index 185ad0d3..8a4485df 100644 --- a/lib/scope.js +++ b/lib/scope.js @@ -38,7 +38,7 @@ ScopeDefinition.prototype.related = function(receiver, scopeParams, condOrRefres if (!self.__cachedRelations || self.__cachedRelations[name] === undefined || actualRefresh) { // It either doesn't hit the cache or refresh is required - var params = mergeParams(actualCond, scopeParams); + var params = mergeQuery(actualCond, scopeParams); return this.targetModel.find(params, function (err, data) { if (!err && saveOnCache) { defineCachedRelations(self); @@ -134,7 +134,7 @@ function defineScope(cls, targetClass, name, params, methods) { Object.defineProperty(f, name, { enumerable: false, get: function () { - mergeParams(f._scope, targetClass._scopeMeta[name]); + mergeQuery(f._scope, targetClass._scopeMeta[name]); return f; } }); @@ -183,15 +183,40 @@ function defineScope(cls, targetClass, name, params, methods) { cls['__delete__' + name] = fn_delete; + /* + * Extracting fixed property values for the scope from the where clause into + * the data object + * + * @param {Object} The data object + * @param {Object} The where clause + */ + function setScopeValuesFromWhere(data, where) { + for (var i in where) { + if (i === 'and') { + // Find fixed property values from each subclauses + for (var w = 0, n = where[i].length; w < n; w++) { + setScopeValuesFromWhere(data, where[i][w]); + } + continue; + } + var prop = targetClass.definition.properties[i]; + if (prop) { + var val = where[i]; + if (typeof val !== 'object' || val instanceof prop.type) { + // Only pick the {propertyName: propertyValue} + data[i] = where[i]; + } + } + } + } + // and it should have create/build methods with binded thisModelNameId param function build(data) { data = data || {}; - var params = mergeParams(this._scope, {where: data}).where; - delete params['and']; - delete params['or']; - delete params['nor']; - - return new targetClass(params); + // Find all fixed property values for the scope + var where = (this._scope && this._scope.where) || {}; + setScopeValuesFromWhere(data, where); + return new targetClass(data); } function create(data, cb) { @@ -209,58 +234,28 @@ function defineScope(cls, targetClass, name, params, methods) { - If fetching the Elements on which destroyAll is called results in an error */ function destroyAll(cb) { - targetClass.find(this._scope, function (err, data) { - if (err) { - cb(err); - } else { - (function loopOfDestruction(data) { - if (data.length > 0) { - data.shift().destroy(function (err) { - if (err && cb) cb(err); - loopOfDestruction(data); - }); - } else { - if (cb) cb(); - } - }(data)); - } - }); + targetClass.destroyAll(this._scope, cb); } } -/*! - * Merge `base` and `update` params - * @param {Object} base - base object (updating this object) - * @param {Object} update - object with new data to update base - * @returns {Object} `base` - * @private - */ -function mergeWhere(base, update) { - base = base || {}; - if (update) { - var keys = Object.keys(update); - for (var k = 0; k < keys.length; k++) { - var key = keys[k]; - base[key] = update[key]; - } - } - return base; -} - /*! * Merge query parameters - * @param base - * @param update - * @returns {*|{}} + * @param {Object} base The base object to contain the merged results + * @param {Object} update The object containing updates to be merged + * @returns {*|Object} The base object * @private */ -function mergeParams(base, update) { +function mergeQuery(base, update) { if (!update) { return; } base = base || {}; - if (update.where) { - base.where = mergeWhere(base.where, update.where); + 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]}; + } else { + base.where = update.where; + } } // Overwrite inclusion diff --git a/test/scope.test.js b/test/scope.test.js index d927bcc7..ecaa8727 100644 --- a/test/scope.test.js +++ b/test/scope.test.js @@ -3,7 +3,7 @@ var should = require('./init.js'); var db, Railway, Station; -describe('sc0pe', function () { +describe('scope', function () { before(function () { db = getSchema();