Rewrite the List class for typed array

This commit is contained in:
Raymond Feng 2014-02-13 23:42:21 -08:00
parent 7e45a1fda1
commit 12a624d99c
6 changed files with 120 additions and 265 deletions

View File

@ -24,20 +24,7 @@ setup(function () {
});
User.find({include: ['posts', 'passports']}, function (err, users) {
// console.log('users.passports && users.posts', users);
users.forEach(function (user) {
console.log('user', user);
user.posts(function (err, posts) {
if (posts && posts.length > 0) {
console.log('posts', posts);
}
});
user.passports(function (err, passports) {
if (passports && passports.length > 0) {
console.log('posts', passports);
}
});
});
console.log('users.passports && users.posts', users);
});
});

View File

@ -29,4 +29,5 @@ var user = new User({name: 'Joe', age: 20, address: {street: '123 Main St', 'cit
{label: 'work', email: 'xyz@sample.com'}
],
friends: ['John', 'Mary']});
console.log(user);
console.log(user.toObject());

View File

@ -6,13 +6,12 @@ module.exports = DataAccessObject;
/**
* Module dependencies
*/
var util = require('util');
var jutil = require('./jutil');
var validations = require('./validations.js');
var ValidationError = validations.ValidationError;
require('./relations.js');
var Inclusion = require('./include.js');
var Relation = require('./relations.js');
var Inclusion = require('./include.js');
var List = require('./list.js');
var geo = require('./geo');
var Memory = require('./connectors/memory').Memory;
var utils = require('./utils');
@ -562,7 +561,11 @@ DataAccessObject.find = function find(params, cb) {
}
includes.forEach(function (inc) {
// Promote the included model as a direct property
obj.__data[inc] = obj.__cachedRelations[inc];
var data = obj.__cachedRelations[inc];
if(Array.isArray(data)) {
data = new List(data, data[0] && [data[0].constructor], obj);
}
obj.__data[inc] = data;
});
delete obj.__data.__cachedRelations;
}

View File

@ -7,11 +7,8 @@ var jutil = require('./jutil');
var utils = require('./utils');
var ModelBaseClass = require('./model.js');
var DataAccessObject = require('./dao.js');
var List = require('./list.js');
var EventEmitter = require('events').EventEmitter;
var util = require('util');
var path = require('path');
var fs = require('fs');
var assert = require('assert');
var async = require('async');

View File

@ -1,154 +1,75 @@
var util = require('util');
module.exports = List;
/**
* List class provides functionality of nested collection
*
* @param {Array} data - array of items.
* @param {Crap} type - array with some type information? TODO: rework this API.
* @param {AbstractClass} parent - owner of list.
* @constructor
*/
function List(data, type, parent) {
function List(items, itemType, parent) {
var list = this;
if (!(list instanceof List)) {
return new List(data, type, parent);
return new List(items, itemType, parent);
}
if (typeof data === 'string') {
if (typeof items === 'string') {
try {
data = JSON.parse(data);
items = JSON.parse(items);
} catch (e) {
throw new Error('could not create List from JSON string: ', data);
throw new Error('could not create List from JSON string: ', items);
}
}
if (data && data instanceof List) data = data.items;
var arr = [];
arr.__proto__ = List.prototype;
Object.defineProperty(list, 'parent', {
writable: false,
enumerable: false,
configurable: false,
value: parent
});
items = items || [];
if (!Array.isArray(items)) {
throw new Error('Items must be an array: ' + items);
}
Object.defineProperty(list, 'nextid', {
if(!itemType) {
itemType = items[0] && items[0].constructor;
}
if (Array.isArray(itemType)) {
itemType = itemType[0];
}
Object.defineProperty(arr, 'itemType', {
writable: true,
enumerable: false,
value: 1
value: itemType
});
data = list.items = data || [];
var Item = list.ItemType = ListItem;
if (typeof type === 'object' && type.constructor.name === 'Array') {
Item = list.ItemType = type[0] || ListItem;
}
data.forEach(function (item, i) {
data[i] = Item(item, list);
Object.defineProperty(list, data[i].id, {
if (parent) {
Object.defineProperty(arr, 'parent', {
writable: true,
enumerable: false,
configurable: true,
value: data[i]
value: parent
});
if (list.nextid <= data[i].id) {
list.nextid = data[i].id + 1;
}
});
Object.defineProperty(list, 'length', {
enumerable: false,
configurable: true,
get: function () {
return list.items.length;
}
});
return list;
}
var _;
try {
var underscore = 'underscore';
_ = require(underscore);
} catch (e) {
_ = false;
}
if (_) {
var _import = [
// collection methods
'each',
'map',
'reduce',
'reduceRight',
'find',
'filter',
'reject',
'all',
'any',
'include',
'invoke',
'pluck',
'max',
'min',
'sortBy',
'groupBy',
'sortedIndex',
'shuffle',
'toArray',
'size',
// array methods
'first',
'initial',
'last',
'rest',
'compact',
'flatten',
'without',
'union',
'intersection',
'difference',
'uniq',
'zip',
'indexOf',
'lastIndexOf',
'range'
];
_import.forEach(function (name) {
List.prototype[name] = function () {
var args = [].slice.call(arguments);
args.unshift(this.items);
return _[name].apply(_, args);
};
});
}
['slice', 'forEach', 'filter', 'reduce', 'map'].forEach(function (method) {
var slice = [].slice;
List.prototype[method] = function () {
return Array.prototype[method].apply(this.items, slice.call(arguments));
};
});
List.prototype.find = function (pattern, field) {
if (field) {
var res;
this.items.forEach(function (o) {
if (o[field] == pattern) res = o;
});
return res;
} else {
return this.items[this.items.indexOf(pattern)];
}
items.forEach(function (item, i) {
if (itemType && !(item instanceof itemType)) {
arr[i] = itemType(item);
} else {
arr[i] = item;
}
});
return arr;
}
util.inherits(List, Array);
var _push = List.prototype.push;
List.prototype.push = function (obj) {
var item = this.itemType && (obj instanceof this.itemType) ? obj : this.itemType(obj);
_push.call(this, item);
return item;
};
List.prototype.toObject = function (onlySchema) {
var items = [];
this.items.forEach(function (item) {
this.forEach(function (item) {
if (item.toObject) {
items.push(item.toObject(onlySchema));
} else {
@ -163,75 +84,15 @@ List.prototype.toJSON = function () {
};
List.prototype.toString = function () {
return JSON.stringify(this.items);
return JSON.stringify(this.toJSON());
};
List.prototype.autoincrement = function () {
return this.nextid++;
};
List.prototype.push = function (obj) {
var item = new ListItem(obj, this);
this.items.push(item);
return item;
};
List.prototype.remove = function (obj) {
var id = obj.id ? obj.id : obj;
var found = false;
this.items.forEach(function (o, i) {
if (id && o.id == id) {
found = i;
if (o.id !== id) {
console.log('WARNING! Type of id not matched');
}
}
});
if (found !== false) {
delete this[id];
this.items.splice(found, 1);
}
};
List.prototype.sort = function (cb) {
return this.items.sort(cb);
};
List.prototype.map = function (cb) {
if (typeof cb === 'function') return this.items.map(cb);
if (typeof cb === 'string') return this.items.map(function (el) {
if (typeof el[cb] === 'function') return el[cb]();
if (el.hasOwnProperty(cb)) return el[cb];
});
};
function ListItem(data, parent) {
if (!(this instanceof ListItem)) {
return new ListItem(data, parent);
}
if (typeof data === 'object') {
for (var i in data) this[i] = data[i];
} else {
this.id = data;
}
Object.defineProperty(this, 'parent', {
writable: false,
enumerable: false,
configurable: true,
value: parent
});
if (!this.id) {
this.id = parent.autoincrement();
}
if (parent.ItemType) {
this.__proto__ = parent.ItemType.prototype;
if (parent.ItemType !== ListItem) {
parent.ItemType.apply(this);
}
}
this.save = function (c) {
parent.parent.save(c);
};
}
/*
var strArray = new List(['1', 2], String);
strArray.push(3);
console.log(strArray);
console.log(strArray.length);
console.log(strArray.toJSON());
console.log(strArray.toString());
*/

View File

@ -1,44 +1,48 @@
module.exports = function (Types) {
var Types = {};
/**
* Schema types
*/
Types.Text = function Text(value) {
if (!(this instanceof Text)) {
return value;
}
this.value = value;
}; // Text type
Types.Text.prototype.toObject = Types.Text.prototype.toJSON = function () {
return this.value;
};
Types.JSON = function JSON(value) {
if (!(this instanceof JSON)) {
return value;
}
this.value = value;
}; // JSON Object
Types.JSON.prototype.toObject = Types.JSON.prototype.toJSON = function () {
return this.value;
};
Types.Any = function Any(value) {
if (!(this instanceof Any)) {
return value;
}
this.value = value;
}; // Any Type
Types.Any.prototype.toObject = Types.Any.prototype.toJSON = function () {
return this.value;
};
module.exports = function (modelTypes) {
var List = require('./list.js');
var GeoPoint = require('./geo').GeoPoint;
/**
* Schema types
*/
Types.Text = function Text(value) {
if (!(this instanceof Text)) {
return value;
}
this.value = value;
}; // Text type
for(var t in Types) {
modelTypes[t] = Types[t];
}
Types.Text.prototype.toObject = Types.Text.prototype.toJSON = function () {
return this.value;
};
Types.JSON = function JSON(value) {
if (!(this instanceof JSON)) {
return value;
}
this.value = value;
}; // JSON Object
Types.JSON.prototype.toObject = Types.JSON.prototype.toJSON = function () {
return this.value;
};
Types.Any = function Any(value) {
if (!(this instanceof Any)) {
return value;
}
this.value = value;
}; // Any Type
Types.Any.prototype.toObject = Types.Any.prototype.toJSON = function () {
return this.value;
};
Types.schemaTypes = {};
Types.registerType = function (type, names) {
modelTypes.schemaTypes = {};
modelTypes.registerType = function (type, names) {
names = names || [];
names = names.concat([type.name]);
for (var n = 0; n < names.length; n++) {
@ -46,16 +50,18 @@ module.exports = function (Types) {
}
};
Types.registerType(Types.Text);
Types.registerType(Types.JSON);
Types.registerType(Types.Any);
modelTypes.registerType(Types.Text);
modelTypes.registerType(Types.JSON);
modelTypes.registerType(Types.Any);
Types.registerType(String);
Types.registerType(Number);
Types.registerType(Boolean);
Types.registerType(Date);
Types.registerType(Buffer, ['Binary']);
Types.registerType(Array);
Types.registerType(GeoPoint);
Types.registerType(Object);
};
modelTypes.registerType(String);
modelTypes.registerType(Number);
modelTypes.registerType(Boolean);
modelTypes.registerType(Date);
modelTypes.registerType(Buffer, ['Binary']);
modelTypes.registerType(Array);
modelTypes.registerType(GeoPoint);
modelTypes.registerType(Object);
};
module.exports.Types = Types;