Merge pull request #597 from strongloop/feature/enhance-fields-to-array
Enhance fieldsToArray to consider strict mode
This commit is contained in:
commit
5af6bf54df
|
@ -947,7 +947,7 @@ DataAccessObject._normalize = function (filter) {
|
||||||
// normalize fields as array of included property names
|
// normalize fields as array of included property names
|
||||||
if (filter.fields) {
|
if (filter.fields) {
|
||||||
filter.fields = fieldsToArray(filter.fields,
|
filter.fields = fieldsToArray(filter.fields,
|
||||||
Object.keys(this.definition.properties));
|
Object.keys(this.definition.properties), this.settings.strict);
|
||||||
}
|
}
|
||||||
|
|
||||||
filter = removeUndefined(filter);
|
filter = removeUndefined(filter);
|
||||||
|
|
|
@ -181,8 +181,9 @@ ModelBaseClass.prototype._initProperties = function (data, options) {
|
||||||
} else if (ctor.relations[p]) {
|
} else if (ctor.relations[p]) {
|
||||||
var relationType = ctor.relations[p].type;
|
var relationType = ctor.relations[p].type;
|
||||||
|
|
||||||
|
var modelTo;
|
||||||
if (!properties[p]) {
|
if (!properties[p]) {
|
||||||
var modelTo = ctor.relations[p].modelTo || ModelBaseClass;
|
modelTo = ctor.relations[p].modelTo || ModelBaseClass;
|
||||||
var multiple = ctor.relations[p].multiple;
|
var multiple = ctor.relations[p].multiple;
|
||||||
var typeName = multiple ? 'Array' : modelTo.modelName;
|
var typeName = multiple ? 'Array' : modelTo.modelName;
|
||||||
var propType = multiple ? [modelTo] : modelTo;
|
var propType = multiple ? [modelTo] : modelTo;
|
||||||
|
@ -196,7 +197,8 @@ ModelBaseClass.prototype._initProperties = function (data, options) {
|
||||||
self.__data[ctor.relations[p].keyFrom] = propVal[ctor.relations[p].keyTo];
|
self.__data[ctor.relations[p].keyFrom] = propVal[ctor.relations[p].keyTo];
|
||||||
|
|
||||||
if (ctor.relations[p].options.embedsProperties) {
|
if (ctor.relations[p].options.embedsProperties) {
|
||||||
var fields = fieldsToArray(ctor.relations[p].properties, modelTo.definition.properties);
|
var fields = fieldsToArray(ctor.relations[p].properties,
|
||||||
|
modelTo.definition.properties, modelTo.setting.strict);
|
||||||
if (!~fields.indexOf(ctor.relations[p].keyTo)) {
|
if (!~fields.indexOf(ctor.relations[p].keyTo)) {
|
||||||
fields.push(ctor.relations[p].keyTo);
|
fields.push(ctor.relations[p].keyTo);
|
||||||
}
|
}
|
||||||
|
|
73
lib/utils.js
73
lib/utils.js
|
@ -149,7 +149,7 @@ function mergeQuery(base, update, spec) {
|
||||||
}
|
}
|
||||||
spec = spec || {};
|
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]};
|
||||||
|
@ -178,81 +178,96 @@ function mergeQuery(base, update, spec) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (spec.collect !== false && update.collect) {
|
if (spec.collect !== false && update.collect) {
|
||||||
base.collect = update.collect;
|
base.collect = update.collect;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Overwrite fields
|
// Overwrite fields
|
||||||
if (spec.fields !== false && update.fields !== undefined) {
|
if (spec.fields !== false && update.fields !== undefined) {
|
||||||
base.fields = update.fields;
|
base.fields = update.fields;
|
||||||
} else if (update.fields !== undefined) {
|
} else if (update.fields !== undefined) {
|
||||||
base.fields = [].concat(base.fields).concat(update.fields);
|
base.fields = [].concat(base.fields).concat(update.fields);
|
||||||
}
|
}
|
||||||
|
|
||||||
// set order
|
// set order
|
||||||
if ((!base.order || spec.order === false) && update.order) {
|
if ((!base.order || spec.order === false) && update.order) {
|
||||||
base.order = update.order;
|
base.order = update.order;
|
||||||
}
|
}
|
||||||
|
|
||||||
// overwrite pagination
|
// overwrite pagination
|
||||||
if (spec.limit !== false && update.limit !== undefined) {
|
if (spec.limit !== false && update.limit !== undefined) {
|
||||||
base.limit = update.limit;
|
base.limit = update.limit;
|
||||||
}
|
}
|
||||||
|
|
||||||
var skip = spec.skip !== false && spec.offset !== false;
|
var skip = spec.skip !== false && spec.offset !== false;
|
||||||
|
|
||||||
if (skip && update.skip !== undefined) {
|
if (skip && update.skip !== undefined) {
|
||||||
base.skip = update.skip;
|
base.skip = update.skip;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (skip && update.offset !== undefined) {
|
if (skip && update.offset !== undefined) {
|
||||||
base.offset = update.offset;
|
base.offset = update.offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
return base;
|
return base;
|
||||||
}
|
}
|
||||||
|
|
||||||
function fieldsToArray(fields, properties) {
|
/**
|
||||||
|
* Normalize fields to an array of included properties
|
||||||
|
* @param {String|String[]|Object} fields Fields filter
|
||||||
|
* @param {String[]} properties Property names
|
||||||
|
* @param {Boolean} excludeUnknown To exclude fields that are unknown properties
|
||||||
|
* @returns {String[]} An array of included property names
|
||||||
|
*/
|
||||||
|
function fieldsToArray(fields, properties, excludeUnknown) {
|
||||||
if (!fields) return;
|
if (!fields) return;
|
||||||
|
|
||||||
// include all properties by default
|
// include all properties by default
|
||||||
var result = properties;
|
var result = properties;
|
||||||
|
var i, n;
|
||||||
|
|
||||||
if (typeof fields === 'string') {
|
if (typeof fields === 'string') {
|
||||||
return [fields];
|
result = [fields];
|
||||||
}
|
} else if (Array.isArray(fields) && fields.length > 0) {
|
||||||
|
|
||||||
if (Array.isArray(fields) && fields.length > 0) {
|
|
||||||
// No empty array, including all the fields
|
// No empty array, including all the fields
|
||||||
return fields;
|
result = fields;
|
||||||
}
|
} else if ('object' === typeof fields) {
|
||||||
|
|
||||||
if ('object' === typeof fields) {
|
|
||||||
// { field1: boolean, field2: boolean ... }
|
// { field1: boolean, field2: boolean ... }
|
||||||
var included = [];
|
var included = [];
|
||||||
var excluded = [];
|
var excluded = [];
|
||||||
var keys = Object.keys(fields);
|
var keys = Object.keys(fields);
|
||||||
if (!keys.length) return;
|
if (!keys.length) return;
|
||||||
|
|
||||||
keys.forEach(function (k) {
|
for (i = 0, n = keys.length; i < n; i++) {
|
||||||
|
var k = keys[i];
|
||||||
if (fields[k]) {
|
if (fields[k]) {
|
||||||
included.push(k);
|
included.push(k);
|
||||||
} else if ((k in fields) && !fields[k]) {
|
} else if ((k in fields) && !fields[k]) {
|
||||||
excluded.push(k);
|
excluded.push(k);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
if (included.length > 0) {
|
if (included.length > 0) {
|
||||||
result = included;
|
result = included;
|
||||||
} else if (excluded.length > 0) {
|
} else if (excluded.length > 0) {
|
||||||
excluded.forEach(function (e) {
|
for (i = 0, n = excluded.length; i < n; i++) {
|
||||||
var index = result.indexOf(e);
|
var index = result.indexOf(excluded[i]);
|
||||||
result.splice(index, 1);
|
result.splice(index, 1);
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
var fieldArray = [];
|
||||||
|
if (excludeUnknown) {
|
||||||
|
for (i = 0, n = result.length; i < n; i++) {
|
||||||
|
if (properties.indexOf(result[i]) !== -1) {
|
||||||
|
fieldArray.push(result[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fieldArray = result;
|
||||||
|
}
|
||||||
|
return fieldArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
function selectFields(fields) {
|
function selectFields(fields) {
|
||||||
|
@ -404,16 +419,16 @@ function sortObjectsByIds(idName, ids, objects, strict) {
|
||||||
ids = ids.map(function(id) {
|
ids = ids.map(function(id) {
|
||||||
return (typeof id === 'object') ? String(id) : id;
|
return (typeof id === 'object') ? String(id) : id;
|
||||||
});
|
});
|
||||||
|
|
||||||
var indexOf = function(x) {
|
var indexOf = function(x) {
|
||||||
var isObj = (typeof x[idName] === 'object'); // ObjectID
|
var isObj = (typeof x[idName] === 'object'); // ObjectID
|
||||||
var id = isObj ? String(x[idName]) : x[idName];
|
var id = isObj ? String(x[idName]) : x[idName];
|
||||||
return ids.indexOf(id);
|
return ids.indexOf(id);
|
||||||
};
|
};
|
||||||
|
|
||||||
var heading = [];
|
var heading = [];
|
||||||
var tailing = [];
|
var tailing = [];
|
||||||
|
|
||||||
objects.forEach(function(x) {
|
objects.forEach(function(x) {
|
||||||
if (typeof x === 'object') {
|
if (typeof x === 'object') {
|
||||||
var idx = indexOf(x);
|
var idx = indexOf(x);
|
||||||
|
@ -421,7 +436,7 @@ function sortObjectsByIds(idName, ids, objects, strict) {
|
||||||
idx === -1 ? tailing.push(x) : heading.push(x);
|
idx === -1 ? tailing.push(x) : heading.push(x);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
heading.sort(function(x, y) {
|
heading.sort(function(x, y) {
|
||||||
var a = indexOf(x);
|
var a = indexOf(x);
|
||||||
var b = indexOf(y);
|
var b = indexOf(y);
|
||||||
|
@ -430,7 +445,7 @@ function sortObjectsByIds(idName, ids, objects, strict) {
|
||||||
if (a > b) return 1;
|
if (a > b) return 1;
|
||||||
if (a < b) return -1;
|
if (a < b) return -1;
|
||||||
});
|
});
|
||||||
|
|
||||||
return heading.concat(tailing);
|
return heading.concat(tailing);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -7,16 +7,17 @@ var mergeIncludes = utils.mergeIncludes;
|
||||||
var sortObjectsByIds = utils.sortObjectsByIds;
|
var sortObjectsByIds = utils.sortObjectsByIds;
|
||||||
|
|
||||||
describe('util.fieldsToArray', function () {
|
describe('util.fieldsToArray', function () {
|
||||||
it('Turn objects and strings into an array of fields to include when finding models', function () {
|
function sample(fields, excludeUnknown) {
|
||||||
|
var properties = ['foo', 'bar', 'bat', 'baz'];
|
||||||
function sample(fields) {
|
return {
|
||||||
var properties = ['foo', 'bar', 'bat', 'baz'];
|
expect: function (arr) {
|
||||||
return {
|
should.deepEqual(fieldsToArray(fields, properties, excludeUnknown), arr);
|
||||||
expect: function (arr) {
|
|
||||||
should.deepEqual(fieldsToArray(fields, properties), arr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
it('Turn objects and strings into an array of fields' +
|
||||||
|
' to include when finding models', function () {
|
||||||
|
|
||||||
sample(false).expect(undefined);
|
sample(false).expect(undefined);
|
||||||
sample(null).expect(undefined);
|
sample(null).expect(undefined);
|
||||||
|
@ -28,6 +29,19 @@ describe('util.fieldsToArray', function () {
|
||||||
sample({'bat': 0}).expect(['foo', 'bar', 'baz']);
|
sample({'bat': 0}).expect(['foo', 'bar', 'baz']);
|
||||||
sample({'bat': false}).expect(['foo', 'bar', 'baz']);
|
sample({'bat': false}).expect(['foo', 'bar', 'baz']);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should exclude unknown properties', function () {
|
||||||
|
|
||||||
|
sample(false, true).expect(undefined);
|
||||||
|
sample(null, true).expect(undefined);
|
||||||
|
sample({}, true).expect(undefined);
|
||||||
|
sample('foo', true).expect(['foo']);
|
||||||
|
sample(['foo', 'unknown'], true).expect(['foo']);
|
||||||
|
sample({'foo': 1, unknown: 1}, true).expect(['foo']);
|
||||||
|
sample({'bat': true, unknown: true}, true).expect(['bat']);
|
||||||
|
sample({'bat': 0}, true).expect(['foo', 'bar', 'baz']);
|
||||||
|
sample({'bat': false}, true).expect(['foo', 'bar', 'baz']);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('util.removeUndefined', function () {
|
describe('util.removeUndefined', function () {
|
||||||
|
@ -190,7 +204,7 @@ describe('mergeSettings', function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('sortObjectsByIds', function () {
|
describe('sortObjectsByIds', function () {
|
||||||
|
|
||||||
var items = [
|
var items = [
|
||||||
{ id: 1, name: 'a' },
|
{ id: 1, name: 'a' },
|
||||||
{ id: 2, name: 'b' },
|
{ id: 2, name: 'b' },
|
||||||
|
@ -211,7 +225,7 @@ describe('sortObjectsByIds', function () {
|
||||||
var names = sorted.map(function(u) { return u.name; });
|
var names = sorted.map(function(u) { return u.name; });
|
||||||
should.deepEqual(names, ['e', 'c', 'b', 'a', 'd', 'f']);
|
should.deepEqual(names, ['e', 'c', 'b', 'a', 'd', 'f']);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should sort - strict', function() {
|
it('should sort - strict', function() {
|
||||||
var sorted = sortObjectsByIds('id', [5, 3, 2], items, true);
|
var sorted = sortObjectsByIds('id', [5, 3, 2], items, true);
|
||||||
var names = sorted.map(function(u) { return u.name; });
|
var names = sorted.map(function(u) { return u.name; });
|
||||||
|
|
Loading…
Reference in New Issue