Permalink
Browse files

Added typed lists support

  • Loading branch information...
1 parent e396917 commit e938a814e8b3b8aef1294a501a0d173cce02c790 @1602 committed Sep 10, 2012
Showing with 126 additions and 7 deletions.
  1. +19 −3 lib/abstract-class.js
  2. +1 −0 lib/adapters/mysql.js
  3. +1 −0 lib/adapters/postgres.js
  4. +10 −0 lib/adapters/redis2.js
  5. +72 −0 lib/list.js
  6. +4 −1 lib/schema.js
  7. +1 −1 package.json
  8. +18 −2 test/common_test.js
View
@@ -4,8 +4,10 @@
var util = require('util');
var jutil = require('./jutil');
var Validatable = require('./validatable').Validatable;
+var List = require('./list');
var Hookable = require('./hookable').Hookable;
var DEFAULT_CACHE_LIMIT = 1000;
+var BASE_TYPES = ['String', 'Boolean', 'Number', 'Date', 'Text'];
exports.AbstractClass = AbstractClass;
@@ -61,10 +63,16 @@ AbstractClass.prototype._initProperties = function (data, applySetters) {
))
});
- if (properties[attr].type.name === 'JSON' && this[_attr]) {
+ var type = properties[attr].type;
+
+ if (BASE_TYPES.indexOf(type.name) === -1) {
try {
this[_attr] = JSON.parse(this[_attr] + '');
- } catch (e) { }
+ if (type.name === 'Array' || typeof type === 'object' && type.constructor.name === 'Array') {
+ this[_attr] = new List(this[_attr], type, this);
+ }
+ } catch (e) {
+ }
}
// Public setters and getters
@@ -526,11 +534,19 @@ AbstractClass.prototype.toObject = function (onlySchema) {
var properties = ds.properties;
// weird
Object.keys(onlySchema ? properties : this).concat(['id']).forEach(function (property) {
- data[property] = this[property];
+ if (this[property] instanceof List) {
+ data[property] = this[property].toObject();
+ } else {
+ data[property] = this[property];
+ }
}.bind(this));
return data;
};
+AbstractClass.prototype.toJSON = function () {
+ return this.toObject();
+};
+
/**
* Delete object from persistence
*
View
@@ -503,6 +503,7 @@ MySQL.prototype.propertySettingsSQL = function (model, prop) {
function datatype(p) {
var dt = '';
switch (p.type.name) {
+ default:
case 'String':
case 'JSON':
dt = 'VARCHAR(' + (p.limit || 255) + ')';
View
@@ -515,6 +515,7 @@ function escape(val) {
function datatype(p) {
switch (p.type.name) {
+ default:
case 'String':
case 'JSON':
return 'varchar';
View
@@ -177,6 +177,10 @@ BridgeToRedis.prototype.forDb = function (model, data) {
for (var i in data) {
if (p[i] && p[i].type.name === 'Date') {
data[i] = data[i] && data[i].getTime ? data[i].getTime() : 0;
+ } else if (p[i] && [
+ 'String', 'Text', 'Number', 'Boolean', 'Date'
+ ].indexOf(p[i].type.name) === -1) {
+ data[i] = JSON.stringify(data[i]);
}
}
return data;
@@ -193,6 +197,12 @@ BridgeToRedis.prototype.fromDb = function (model, data) {
data[i] = new Date();
data[i].setTime(ms);
}
+ } else if (p[i] && [
+ 'String', 'Text', 'Number', 'Boolean', 'Date'
+ ].indexOf(p[i].type.name) === -1) {
+ try {
+ data[i] = JSON.parse(data[i]);
+ } catch (e) {}
}
}
return data;
View
@@ -0,0 +1,72 @@
+
+module.exports = List;
+
+function List(data, type, parent) {
+ this.parent = parent;
+ this.nextid = 1;
+ data = this.items = data || [];
+ var Item = this.ItemType = ListItem;
+
+ if (typeof type === 'object' && type.constructor.name === 'Array') {
+ this.ItemType = Item = type[0] || ListItem;
+ }
+
+ data.forEach(function (item) {
+ data[i] = new Item(item, parent);
+ });
+}
+
+List.prototype.toObject = function () {
+ return this.items;
+};
+
+List.prototype.autoincrement = function () {
+ return this.nextid++;
+};
+
+List.prototype.push = function (obj) {
+ var item = new ListItem(obj, this);
+ if (this.ItemType) {
+ item.__proto__ = this.ItemType.prototype;
+ }
+ item.id = this.autoincrement();
+ this.items.push(item);
+ return item;
+};
+
+List.prototype.remove = function (obj) {
+ var found;
+ this.items.forEach(function (o, i) {
+ if (o.id === obj.id) found = i;
+ });
+ if (found) {
+ this.items.splice(i, 1);
+ }
+};
+
+List.prototype.forEach = function (cb) {
+ this.items.forEach(cb);
+};
+
+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) {
+ for (var i in data) this[i] = data[i];
+ Object.defineProperty(this, 'parent', {
+ writable: false,
+ enumerable: false,
+ configurable: true,
+ value: parent
+ });
+}
+
View
@@ -181,7 +181,10 @@ Schema.prototype.define = function defineClass(className, properties, settings)
function standartize(properties, settings) {
Object.keys(properties).forEach(function (key) {
var v = properties[key];
- if (typeof v === 'function') {
+ if (
+ typeof v === 'function' ||
+ typeof v === 'object' && v && v.constructor.name === 'Array'
+ ) {
properties[key] = { type: v };
}
});
View
@@ -1,7 +1,7 @@
{
"name": "jugglingdb",
"description": "ORM for every database: redis, mysql, neo4j, mongodb, postgres, sqlite",
- "version": "0.1.16",
+ "version": "0.1.17",
"author": "Anatoliy Chakkaev <rpm1602@gmail.com>",
"contributors": [
{ "name": "Anatoliy Chakkaev", "email": "rpm1602@gmail.com" },
View
@@ -77,9 +77,16 @@ function testOrm(schema) {
title: { type: String, length: 255, index: true },
content: { type: Text },
date: { type: Date, default: function () { return new Date }, index: true },
- published: { type: Boolean, default: false }
+ published: { type: Boolean, default: false },
+ likes: [],
+ related: [RelatedPost]
}, {table: 'posts'});
+ function RelatedPost() { }
+ RelatedPost.prototype.someMethod = function () {
+ return this.parent;
+ };
+
Post.validateAsync('title', function (err, done) {
process.nextTick(done);
});
@@ -154,7 +161,7 @@ function testOrm(schema) {
it('should be expoted to JSON', function (test) {
test.equal(JSON.stringify(new Post({id: 1, title: 'hello, json', date: 1})),
- '{"id":1,"title":"hello, json","content":null,"date":1,"published":false,"userId":null}');
+ '{"id":1,"title":"hello, json","content":null,"date":1,"published":false,"likes":[],"related":[],"userId":null}');
test.done();
});
@@ -800,6 +807,15 @@ function testOrm(schema) {
});
});
+ it('should work with typed and untyped nested collections', function (test) {
+ var post = new Post;
+ var like = post.likes.push({foo: 'bar'});
+ test.equal(like.constructor.name, 'ListItem');
+ var related = post.related.push({hello: 'world'});
+ test.ok(related.someMethod);
+ test.done();
+ });
+
it('all tests done', function (test) {
test.done();
process.nextTick(allTestsDone);

0 comments on commit e938a81

Please sign in to comment.