Skip to content

Commit d0dee61

Browse files
committed
Allow custom property names & custom selects
1 parent 39b90bd commit d0dee61

File tree

10 files changed

+219
-95
lines changed

10 files changed

+219
-95
lines changed

lib/Associations/Many.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,9 @@ exports.prepare = function (Model, associations) {
3535
props = {};
3636
} else {
3737
for (var k in props) {
38-
props[k] = Property.normalize(props[k], {}, Model.settings);
38+
props[k] = Property.normalize({
39+
prop: props[k], name: k, customTypes: {}, settings: Model.settings
40+
});
3941
}
4042
}
4143

@@ -59,7 +61,6 @@ exports.prepare = function (Model, associations) {
5961
delAccessor : opts.delAccessor || ("remove" + assocTemplateName),
6062
addAccessor : opts.addAccessor || ("add" + assocTemplateName)
6163
};
62-
6364
associations.push(association);
6465

6566
if (opts.reverse) {

lib/Instance.js

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -151,11 +151,14 @@ function Instance(Model, opts) {
151151
prop = Model.allProperties[k];
152152

153153
if (prop) {
154-
if (prop.type === 'serial' && opts.data[k] == null) continue;
154+
if (opts.data[k] == null && (prop.type == 'serial' || typeof prop.defaultValue == 'function')) {
155+
continue;
156+
}
155157

156-
data[k] = Property.validate(opts.data[k], prop);
157158
if (opts.driver.propertyToValue) {
158-
data[k] = opts.driver.propertyToValue(data[k], prop);
159+
data[prop.mapsTo] = opts.driver.propertyToValue(opts.data[k], prop);
160+
} else {
161+
data[prop.mapsTo] = opts.data[k];
159162
}
160163
} else {
161164
data[k] = opts.data[k];
@@ -195,7 +198,7 @@ function Instance(Model, opts) {
195198

196199
opts.changes.length = 0;
197200
for (var i = 0; i < opts.id.length; i++) {
198-
opts.data[opts.id[i]] = info.hasOwnProperty(opts.id[i]) ? info[opts.id[i]] : data[opts.id[i]];
201+
opts.data[opts.id[i]] = info.hasOwnProperty(opts.id[i]) ? info[opts.id[i]] : data[opts.id[i]];
199202
}
200203
opts.is_new = false;
201204

@@ -337,7 +340,7 @@ function Instance(Model, opts) {
337340
if (!opts.data.hasOwnProperty(opts.extrachanges[i])) continue;
338341

339342
if (opts.extra[opts.extrachanges[i]]) {
340-
data[opts.extrachanges[i]] = Property.validate(opts.data[opts.extrachanges[i]], opts.extra[opts.extrachanges[i]]);
343+
data[opts.extrachanges[i]] = opts.data[opts.extrachanges[i]];
341344
if (opts.driver.propertyToValue) {
342345
data[opts.extrachanges[i]] = opts.driver.propertyToValue(data[opts.extrachanges[i]], opts.extra[opts.extrachanges[i]]);
343346
}
@@ -394,8 +397,7 @@ function Instance(Model, opts) {
394397
changes[key] = value;
395398

396399
if (Model.properties[key]) {
397-
changes[key] = Property.validate(changes[key], Model.properties[key]);
398-
if (opts.driver.propertyToValue) {
400+
if (opts.driver.propertyToValue) {
399401
changes[key] = opts.driver.propertyToValue(changes[key], Model.properties[key]);
400402
}
401403
}

lib/Model.js

Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ function Model(opts) {
3333
var extend_associations = [];
3434
var association_properties = [];
3535
var model_fields = [];
36+
var fieldToPropertyMap = {};
3637
var allProperties = {};
3738

3839
var createHookHelper = function (hook) {
@@ -142,6 +143,18 @@ function Model(opts) {
142143
return instance;
143144
};
144145

146+
var mapDatastoreFieldsToProperties = function (dataIn) {
147+
var k, prop;
148+
var dataOut = {};
149+
150+
for (k in dataIn) {
151+
prop = fieldToPropertyMap[k];
152+
if (!prop) dataOut[k] = dataIn[k];
153+
else dataOut[prop.name] = dataIn[k];
154+
}
155+
return dataOut;
156+
}
157+
145158
var model = function () {
146159
var instance, i;
147160

@@ -283,16 +296,18 @@ function Model(opts) {
283296
return cb(new ORMError(err.message, 'QUERY_ERROR', { originalCode: err.code }));
284297
}
285298
if (data.length === 0) {
286-
return cb(new ORMError("Not found", 'NOT_FOUND', { model: opts.table }));
299+
return cb(new ORMError("Not found", 'NOT_FOUND', { model: opts.table }));
287300
}
288301

302+
data = mapDatastoreFieldsToProperties(data[0]);
303+
289304
var uid = opts.driver.uid + "/" + opts.table + "/" + ids.join("/");
290305

291306
Singleton.get(uid, {
292307
cache : (options.hasOwnProperty("cache") ? options.cache : opts.cache),
293308
save_check : opts.settings.get("instance.cacheSaveCheck")
294309
}, function (cb) {
295-
return createInstance(data[0], {
310+
return createInstance(data, {
296311
uid : uid,
297312
autoSave : options.autoSave,
298313
autoFetch : (options.autoFetchLimit === 0 ? false : options.autoFetch),
@@ -630,22 +645,32 @@ function Model(opts) {
630645
}
631646
}
632647

633-
var cur_fields = {};
648+
var currFields = {}, cType;
649+
634650
// standardize properties
635651
for (k in opts.properties) {
636-
opts.properties[k] = Property.normalize(opts.properties[k], opts.db.customTypes, opts.settings);
637-
opts.properties[k].klass = 'primary';
638-
allProperties[k] = opts.properties[k];
652+
var prop = opts.properties[k] = Property.normalize({
653+
prop: opts.properties[k], name: k,
654+
customTypes: opts.db.customTypes, settings: opts.settings
655+
});
656+
prop.klass = 'primary';
657+
allProperties[k] = prop;
658+
fieldToPropertyMap[prop.mapsTo] = prop;
639659

640660
if (opts.id.indexOf(k) != -1) {
641-
opts.properties[k].key = true;
661+
prop.key = true;
642662
}
643-
644-
if (opts.properties[k].lazyload !== true && !cur_fields[k]) {
645-
cur_fields[k] = true;
646-
model_fields.push(opts.properties[k].select || k);
663+
if (prop.lazyload !== true && !currFields[k]) {
664+
currFields[k] = true;
665+
if ((cType = opts.db.customTypes[prop.type]) && cType.datastoreGet) {
666+
model_fields.push({
667+
a: prop.mapsTo, sql: cType.datastoreGet(prop, opts.db.driver.query)
668+
});
669+
} else {
670+
model_fields.push(prop.mapsTo);
671+
}
647672
}
648-
if (opts.properties[k].required) {
673+
if (prop.required) {
649674
// Prepend `required` validation
650675
if(opts.validations.hasOwnProperty(k)) {
651676
opts.validations[k].splice(0, 0, Validators.required());
@@ -657,9 +682,11 @@ function Model(opts) {
657682

658683
for (var i = 0; i < opts.id.length; i++) {
659684
k = opts.id[i];
660-
allProperties[k] = opts.properties[k] || {
661-
type: 'serial', key: true, klass: 'key'
662-
};
685+
allProperties[k] = opts.properties[k] || Property.normalize({
686+
prop: {type: 'serial', key: true, klass: 'key'},
687+
name: k, customTypes: opts.db.customTypes, settings: opts.settings
688+
});
689+
fieldToPropertyMap[allProperties[k].mapsTo] = allProperties[k];
663690
}
664691
model_fields = opts.id.concat(model_fields);
665692

lib/Property.js

Lines changed: 38 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3,59 +3,68 @@ var ORMError = require("./Error");
33
var KNOWN_TYPES = [
44
"text", "number", "integer", "boolean", "date", "enum", "object",
55
"binary", "point", "serial"
6-
]
6+
];
77

8-
exports.normalize = function (prop, customTypes, Settings) {
9-
if (typeof prop === "function") {
10-
switch (prop.name) {
8+
9+
exports.normalize = function (opts) {
10+
if (typeof opts.prop === "function") {
11+
switch (opts.prop.name) {
1112
case "String":
12-
prop = { type: "text" };
13+
opts.prop = { type: "text" };
1314
break;
1415
case "Number":
15-
prop = { type: "number" };
16+
opts.prop = { type: "number" };
1617
break;
1718
case "Boolean":
18-
prop = { type: "boolean" };
19+
opts.prop = { type: "boolean" };
1920
break;
2021
case "Date":
21-
prop = { type: "date" };
22+
opts.prop = { type: "date" };
2223
break;
2324
case "Object":
24-
prop = { type: "object" };
25+
opts.prop = { type: "object" };
2526
break;
2627
case "Buffer":
27-
prop = { type: "binary" };
28+
opts.prop = { type: "binary" };
2829
break;
2930
}
30-
} else if (typeof prop === "string") {
31-
var tmp = prop;
32-
prop = {};
33-
prop.type = tmp;
34-
} else if (Array.isArray(prop)) {
35-
prop = { type: "enum", values: prop };
31+
} else if (typeof opts.prop === "string") {
32+
var tmp = opts.prop;
33+
opts.prop = {};
34+
opts.prop.type = tmp;
35+
} else if (Array.isArray(opts.prop)) {
36+
opts.prop = { type: "enum", values: opts.prop };
3637
}
3738

38-
if (KNOWN_TYPES.indexOf(prop.type) === -1 && !(prop.type in customTypes)) {
39-
throw new ORMError("Unknown property type: " + prop.type, 'NO_SUPPORT');
39+
if (KNOWN_TYPES.indexOf(opts.prop.type) === -1 && !(opts.prop.type in customTypes)) {
40+
throw new ORMError("Unknown property type: " + opts.prop.type, 'NO_SUPPORT');
41+
}
42+
43+
if ([ "text", "number", "boolean", "serial", "date", "enum", "object", "binary", "point" ].indexOf(opts.prop.type) === -1) {
44+
if (!(opts.prop.type in opts.customTypes)) {
45+
throw new ORMError("Unknown opts.property type: " + opts.prop.type, 'NO_SUPPORT');
46+
}
4047
}
4148

42-
if (!prop.hasOwnProperty("required") && Settings.get("properties.required")) {
43-
prop.required = true;
49+
if (!opts.prop.hasOwnProperty("required") && opts.settings.get("properties.required")) {
50+
opts.prop.required = true;
4451
}
4552

4653
// Defaults to true. Rational means floating point here.
47-
if (prop.type == "number" && prop.rational === undefined) {
48-
prop.rational = true;
54+
if (opts.prop.type == "number" && opts.prop.rational === undefined) {
55+
opts.prop.rational = true;
4956
}
5057

51-
if (prop.type == "number" && prop.rational === false) {
52-
prop.type = "integer";
53-
delete prop.rational;
58+
if (!('mapsTo' in opts.prop)) {
59+
opts.prop.mapsTo = opts.name
5460
}
5561

56-
return prop;
57-
};
62+
if (opts.prop.type == "number" && opts.prop.rational === false) {
63+
opts.prop.type = "integer";
64+
delete opts.prop.rational;
65+
}
66+
67+
opts.prop.name = opts.name;
5868

59-
exports.validate = function (value, prop) {
60-
return value;
69+
return opts.prop;
6170
};

lib/Utilities.js

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
_ = require('lodash')
2+
13
/**
24
* Order should be a String (with the property name assumed ascending)
35
* or an Array or property String names.
@@ -176,7 +178,12 @@ exports.wrapFieldObject = function (obj, model, altName, alternatives) {
176178

177179
var new_obj = {};
178180

179-
new_obj[obj] = alternatives[obj] || alternatives[model.id[0]] || { type: 'number', unsigned: true, rational: false };
181+
new_obj[obj] = _.cloneDeep(
182+
alternatives[obj] || alternatives[model.id[0]] || { type: 'number', unsigned: true, rational: false }
183+
);
184+
new_obj[obj].name = obj;
185+
new_obj[obj].mapsTo = obj;
186+
180187

181188
return new_obj;
182189
};
@@ -206,14 +213,18 @@ exports.formatField = function (model, name, required, reversed) {
206213
time : p.time || false,
207214
big : p.big || false,
208215
values : p.values || null,
209-
required : required
216+
required : required,
217+
name : field_name,
218+
mapsTo : field_name
210219
};
211220
} else {
212221
field_opts = {
213222
type : "integer",
214223
unsigned : true,
215224
size : 4,
216-
required : required
225+
required : required,
226+
name : field_name,
227+
mapsTo : field_name
217228
};
218229
}
219230

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@
3737
"analyse" : false,
3838
"dependencies": {
3939
"enforce" : "0.1.2",
40-
"sql-query" : "0.1.16",
41-
"sql-ddl-sync" : "git://github.com/dresende/node-sql-ddl-sync.git#v0.3.0",
40+
"sql-query" : "git://github.com/dresende/node-sql-query.git#custom-properties",
41+
"sql-ddl-sync" : "git://github.com/dresende/node-sql-ddl-sync.git#custom-properties",
4242
"hat" : "0.0.3",
4343
"lodash" : "2.4.1"
4444
},

0 commit comments

Comments
 (0)