Skip to content

Commit

Permalink
Cross-entities queries
Browse files Browse the repository at this point in the history
  • Loading branch information
Anatoliy Chakkaev committed Nov 16, 2010
1 parent 3ad4fe0 commit cc001e2
Showing 1 changed file with 119 additions and 11 deletions.
130 changes: 119 additions & 11 deletions lib/orm.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,16 @@ var redis = redis_lib.createClient();
exports.debugMode = false;
exports.useCache = false;

function ucwords(str) {
str = str.split("_");

for (i = 0; i < str.length; ++i) {
str[i] = str[i].substring(0, 1).toUpperCase() + str[i].substring(1).toLowerCase();
}

return str.join('');
}

function cast_type_from_db(Model, attr, data) {
switch (Model.attributes[attr]) {
case 'int':
Expand All @@ -18,10 +28,23 @@ function cast_type_from_db(Model, attr, data) {
case 'string':
data = data.toString();
break;
case 'json':
console.log(data.toString());
data = JSON.parse(data.toString());
break;
}
return data;
}

function cast_type_for_db(Model, attr, data) {
if (Model.attributes[attr] == 'json') {
console.log(JSON.stringify(data));
return JSON.stringify(data);
} else {
return data.toString();
}
}

// function construct(constructor, args) {
// function F() {
// return constructor.apply(this, args);
Expand All @@ -39,21 +62,23 @@ function cast_type_from_db(Model, attr, data) {
// return arr;
// }

function add_persistence_methods(Model, model_name) {
function add_persistence_methods(Model, model_name, namespace) {

Model.connection = redis;
Model.redis = redis_lib;
Model.prototype.connection = redis;
Model.attributes.created_at = 'datetime';

Model.create = function (params, callback) {
Model.create = function (params) {
var callback = arguments[arguments.length - 1];
if (exports.debugMode)
sys.debug("[create new " + model_name + "]");

var self = new Model; // construct(Model, prepare_arguments(arguments));
for (var i in params) {
self[i] = params[i];
if (arguments.length == 2) {
for (var i in params) {
self[i] = params[i];
}
}
redis.incr('ids:' + model_name.toLowerCase(), function (err, id) {
if (!err) {
Expand All @@ -80,7 +105,8 @@ function add_persistence_methods(Model, model_name) {
sys.debug('[called set method ' + attr + ' of ' + model_name + ']');
}
if (Model.attributes[attr]) {
redis.hset(model_name.toLowerCase() + ':' + this.id, attr, value.toString(), function (err) {
console.log('update attrib', this.id, attr, value);
redis.hset(model_name.toLowerCase() + ':' + this.id, attr, cast_type_for_db(Model, attr, value), function (err) {
self[attr] = value;
if (typeof callback == 'function') {
callback.apply(self, [err]);
Expand All @@ -93,12 +119,23 @@ function add_persistence_methods(Model, model_name) {
}
};

Model.prototype.save = function (callback) {
Model.prototype.save = function (data, callback) {
var wait = 0, error = false, callback_applied = false;
if (typeof data == 'function') {
callback = data;
data = {};
}
for (var attr in Model.attributes) {
console.log(attr);
console.log(this);
if (Model.attributes.hasOwnProperty(attr) && typeof this[attr] !== 'undefined') {
console.log(attr);
console.log(typeof callback);
if (typeof callback == 'function') {
++wait;
if (typeof data[attr] !== 'undefined') {
this[attr] = data[attr];
}
this.update_attribute(attr, this[attr], function (err) {
--wait;
error = error || err;
Expand All @@ -114,7 +151,41 @@ function add_persistence_methods(Model, model_name) {
}
};

Model.prototype.get = function (attr, callback) {
var submodel_name = Model.attributes[attr];
if (submodel_name == 'string' || submodel_name == 'int' || submodel_name == 'datetime') {
callback(this[attr]);
return;
}
if (namespace) {
console.log('getter with namespace');
console.log(this[attr]);
namespace[ucwords(submodel_name)].find(this[attr], function () {
console.log(this);
console.log(arguments);
callback(this);
});
} else {
this.connection.hgetall(submodel_name + ':' + this[attr], function (err, hash) {
var new_hash = {};
for (var i in hash) {
new_hash[i] = cast_type_from_db(Model, i, hash[i].toString());
}
callback(new_hash);
});
}
};

Model.prototype.to_hash = function () {
var hash = {};
for (var i in Model.attributes) {
hash[i] = this[i];
}
return hash;
};

Model.prototype.reload = function (callback) {
var self = this;
if (!this.id) {
if (typeof callback == 'function') {
callback.apply(this, [true]);
Expand All @@ -124,9 +195,10 @@ function add_persistence_methods(Model, model_name) {
var self = this;
redis.hgetall(model_name.toLowerCase() + ':' + this.id, function (err, hash) {
for (var attr in hash) {
this[attr] = cast_type_from_db(Model, attr, hash[attr]);
self[attr] = cast_type_from_db(Model, attr, hash[attr]);
}
callback.apply(this, [err]);
if (self.initialize) self.initialize();
callback.apply(self, [err]);
});
};

Expand Down Expand Up @@ -179,7 +251,13 @@ function add_persistence_methods(Model, model_name) {
// }
// }

// define object batch loader
/**
* Find object in database
* @param {Number} id identifier of record
* @param {Function} callback(err) Function will be called after search
* it accepts one argument: error, applies to object
*
*/
Model.find = function (id, callback) {
if (exports.debugMode) {
sys.debug('[fetch hash from storage]');
Expand All @@ -190,14 +268,15 @@ function add_persistence_methods(Model, model_name) {
for (var attr in hash) {
if (!obj) {
obj = new Model;
obj.id = id;
}
obj[attr] = cast_type_from_db(Model, attr, hash[attr]);
}
}
if (obj && obj.initialize) {
obj.initialize();
}
if (typeof callback == 'function') callback.apply(obj, [err || obj ? null : true]);
if (typeof callback == 'function') callback.call(obj, err || obj ? null : true);
});
};

Expand All @@ -209,6 +288,35 @@ function add_persistence_methods(Model, model_name) {
});
};

Model.find_or_create = function (id, callback) {
Model.exists(id, function (exists) {
if (exists) {
Model.find(id, callback);
} else {
var obj = new Model;
obj.id = id;
obj.created_at = new Date;
obj.save(callback);
}
});
};

Model.update_or_create = function (data, callback) {
Model.exists(data.id, function (exists) {
if (exists) {
Model.find(id, function () {
this.save(data, function () {
callback.call(this);
});
});
} else {
Model.create(data, function () {
callback.call(this);
});
}
});
};

Model.prototype.destroy = function (callback) {
var self = this;
redis.del(model_name.toLowerCase() + ':' + this.id, function (err, succ) {
Expand All @@ -225,7 +333,7 @@ exports.mix_persistence_methods = function (model_or_collection, model_name) {
} else {
for (var model in model_or_collection) {
if (typeof model_or_collection[model] == 'function') {
add_persistence_methods(model_or_collection[model], model);
add_persistence_methods(model_or_collection[model], model, model_or_collection);
}
}
}
Expand Down

0 comments on commit cc001e2

Please sign in to comment.