cody
Version:
287 lines (238 loc) • 9.23 kB
JavaScript
//
// Johan Coppieters - apr 2014 - Cody - beta 1
//
// beta 2: added "label" and "hide" in cols.
// added loopLabelList (for iterating over the cols)
//
// planned: beta 3: remove console.log's
//
var cody = require("../index.js");
console.log("loading " + module.id);
function Model(theController, options) {
if (theController != null) {
this.controller = theController;
theController.model = this;
}
this.tableName = options.tableName;
this.id = options.id || {name: "id", def: 0};
// cols: array with objects containing meta data and values
// {name: "username", def: "", list: true, sort: "asc", q: "like"}
//
// name=..., def=default value, list=appears with doList is called, sort...,
// like=when there are q.name params use this operator
this.cols = options.cols;
// refs: array with objects containing per reference table
// - (name, query) to be fetched and set upon "doGet" or
// - (name, array) to be set upon "doGet"
//
this.refs = options.refs || [];
}
module.exports = Model;
/* Example: User model
var aUser = new cody.Model(this, {
tableName: "patients",
id: {name: "id", def: 0},
cols: [
{name: "name", def: "", list: true, sort: "asc"},
{name: "firstname", def: "", list: true, sort: "asc"},
{name: "street", label: "Street", def: "", list: true},
{name: "town", label: "Town", def: "", list: true},
{name: "tel1", label: "Phone 1", def: "", list: true},
{name: "tel2", label: "Phone 2", def: "", list: true},
{name: "active", label: "Active", def: "Y", list: true, hide: true},
{name: "email", label: "Email", def: "", list: true}]
});
*/
Model.prototype.addRef = function(name, list) {
this.refs.push({name: name, list: list});
};
Model.prototype.getId = function() {
return (typeof this.id.val !== "undefined") ? this.id.val : this.id.def;
};
Model.prototype.getString = function() {
var n = this.cols.reduce(function(prev, curr) { return prev + ((curr.name === "name") ? curr.val : ""); }, "");
return n + " [" + this.id.name + "=" + this.id.val + "]";
};
Model.prototype.getEmpty = function() {
var r = {};
r[this.id.name] = this.id.def;
return r;
};
Model.prototype.getNameList = function() {
return this.cols
.map(function(ele) { return ele.name; })
.join(", ");
};
Model.prototype.getUpdateList = function() {
return this.cols
.map(function(ele) { return ele.name + "=?"; })
.join(", ");
};
Model.prototype.getListList = function() {
return this.cols
.filter(function(ele) { return ele.list; })
.map(function(ele) { return ele.name; })
.join(", ");
};
Model.prototype.loopLabelList = function(render) {
this.cols
.filter(function(ele) { return ele.list && ! ele.hide; })
.forEach(function(ele) { render(ele.label); });
}
Model.prototype.getOrderBy = function() {
return this.cols
.filter(function(ele) { return ele.sort; })
.map(function(ele) { return ele.name + " " + ele.sort; })
.join(", ");
};
Model.prototype.getWhere = function() {
var wl = this.cols
.filter(function(ele) { return ele.q; })
.map(function(ele) { return ele.name+" "+ele.q+" ?"; })
.join(" and ");
return (wl.length === 0) ? "" : " where " + wl;
};
Model.prototype.makeInsert = function() {
var qs = this.cols.map(function(ele) { return "?"; }).join(",");
return "insert into " + this.tableName + " (" + this.getNameList() + ") " + " values (" + qs + ")";
};
Model.prototype.makeUpdate = function() {
return "update " + this.tableName + " set " + this.getUpdateList() + " where " + this.id.name + " = ?";
};
Model.prototype.makeSelect = function() {
return "select " + this.id.name + "," + this.getNameList() + " from " + this.tableName + " where " + this.id.name + " = ?";
};
Model.prototype.makeDelete = function() {
return "delete from " + this.tableName + " where " + this.id.name + " = ?";
};
Model.prototype.makeList = function() {
return "select " + this.id.name + "," + this.getListList() + " from " + this.tableName + this.getWhere() + " order by " + this.getOrderBy();
};
Model.prototype.scrapeFrom = function() {
var self = this;
self.cols.forEach(function(ele) {
ele.val = self.controller.getParam(ele.name, ele.def);
if (Array.isArray(ele.val)) ele.val = ele.val.join(",");
console.log("scraped: " + ele.name + " = " + ele.val);
});
self.id.val = self.controller.getParam(self.id.name, self.id.def);
console.log("scraped: " + self.getString());
};
Model.prototype.doDelete = function( theId, finish ) {
var self = this;
self.controller.query(self.makeDelete(), [theId], function(err, result) {
if (err) {
self.controller.feedBack(false, "Failed to delete the record " + theId + " from " + self.tableName);
} else {
self.controller.feedBack(true, "Successfully deleted a record " + theId + " from " + self.tableName);
}
finish();
});
};
Model.prototype.doSave = function( finish ) {
var self = this;
var values = self.cols.map(function(ele) { return ele.val; });
if (self.id.val === self.id.def) {
// no id -> a new record -> insert
console.log("query: " + self.makeInsert() + " <- " + values);
self.controller.query(self.makeInsert(), values, function(err, result){
if (err) {
console.log("error inserting into " + self.tableName + " -> " + err);
self.controller.feedBack(true, "Error inserting a record in " + self.tableName);
} else {
self.id.val = result.insertId;
console.log("generated id -> " + self.getString());
self.controller.feedBack(true, "Successfully a record in " + self.tableName);
}
finish();
});
} else {
// an existing record -> update
// add the id to the end of the list
values.push(self.id.val);
console.log("query: " + self.makeUpdate() + " <- " + values);
self.controller.query(self.makeUpdate(), values, function(err, result){
if (err) {
console.log("error updating " + self.tableName + ", record = " + self.getString() + " -> " + err);
self.controller.feedBack(true, "Error updating the record = " + self.getString() + " in " + self.tableName);
} else {
self.controller.feedBack(true, "Successfully updated the record = " + self.getString() + " in " + self.tableName);
}
finish();
});
}
};
Model.prototype.doGetRefs = function(finish) {
var self = this;
cody.Application.each(self.refs, function(done) {
if (typeof this.list === "String") {
// "list" is a string containing a query
self.controller.query(this.list, [], function(err, results) {
self.controller.context[this.name] = results;
done();
});
} else {
// "list" is an array containing the values
self.controller.context[this.name] = this.list;
done();
}
}, finish);
};
Model.prototype.doGet = function(theId, finish) {
var self = this;
self.doGetRefs( function() {
if ((theId === undefined) || isNaN(theId) || (theId === self.id.def)) {
self.controller.context.record = self.getEmpty();
self.id.val = self.id.def;
finish();
} else {
console.log("query: " + self.makeSelect() + " <- " + theId);
self.controller.query(self.makeSelect(), [theId], function(err, result) {
if (result.length > 0) {
self.controller.context.record = result[0];
self.id.val = theId;
} else {
self.controller.context.record = self.getEmpty();
self.id.val = 0;
}
finish();
});
}
});
};
Model.prototype.doList = function(finish) {
var self = this;
// get search params
// - into "record" for reference in the template
// - and into "q" for the query.
var record = {};
var q = [];
self.cols.forEach(function(ele) { console.log("dolist -> " + ele.name + " / " + ele.q);
if (ele.q !== undefined) {
// if this column has a q option set in the model ("like", "=", "<", ...)
var val = self.controller.getParam("q."+ele.name, ele.def);
// if the returned value is an array, we've got a multiple select form element
// convert the returned array in a comma separated list
if (Array.isArray(val)) { val = val.join("%"); }
// remember the value in the "record" element,
// perhaps it is displayed in the search result list
record[ele.name] = val;
// for "like"s we add % before and after, others should match exactly
q.push((ele.q === "like") ? ("%" + val + "%") : val);
}
});
self.controller.context.record = record;
console.log("made search params: " + q.join("|"));
// fetch the list
console.log("list records: " + q.join("|") + " -> " + self.makeList());
self.controller.query(self.makeList(), q, function(err, result) {
if (err) {
console.log("error searching for records " + self.tableName + ", search params = " + q.join("|") + " -> " + err);
console.log("error searching, while using: " + self.makeList());
self.controller.feedBack(true, "Error searching for records in " + self.tableName);
} else {
self.controller.context.records = result;
}
self.doGetRefs(finish);
});
};