Skip to content

Commit 231797a

Browse files
committed
Merge pull request #639 from dresende/bugfixes
Bugfixes
2 parents 1af9b1f + 7d1cb98 commit 231797a

File tree

7 files changed

+245
-60
lines changed

7 files changed

+245
-60
lines changed

lib/Associations/Extend.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@ exports.prepare = function (db, Model, associations) {
1515
reversed : opts.reversed,
1616
autoFetch : opts.autoFetch || false,
1717
autoFetchLimit : opts.autoFetchLimit || 2,
18-
field : util.wrapFieldObject(opts.field, Model, Model.table, Model.properties) || util.formatField(Model, Model.table, false, false),
18+
field : util.wrapFieldObject({
19+
field: opts.field, model: Model, altName: Model.table
20+
}) || util.formatField(Model, Model.table, false, false),
1921
getAccessor : opts.getAccessor || ("get" + assocName),
2022
setAccessor : opts.setAccessor || ("set" + assocName),
2123
hasAccessor : opts.hasAccessor || ("has" + assocName),

lib/Associations/Many.js

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,17 @@ exports.prepare = function (db, Model, associations) {
4444
makeKey = opts.key || Settings.defaults().hasMany.key;
4545

4646
mergeId = util.convertPropToJoinKeyProp(
47-
util.wrapFieldObject(opts.mergeId, Model, Model.table, Model.properties) ||
47+
util.wrapFieldObject({
48+
field: opts.mergeId, model: Model, altName: Model.table
49+
}) ||
4850
util.formatField(Model, Model.table, true, opts.reversed),
4951
{ makeKey: makeKey, required: true }
5052
);
5153

5254
mergeAssocId = util.convertPropToJoinKeyProp(
53-
util.wrapFieldObject(opts.mergeAssocId, OtherModel, name, OtherModel.properties) ||
55+
util.wrapFieldObject({
56+
field: opts.mergeAssocId, model: OtherModel, altName: name
57+
}) ||
5458
util.formatField(OtherModel, name, true, opts.reversed),
5559
{ makeKey: makeKey, required: true }
5660
)
@@ -65,7 +69,10 @@ exports.prepare = function (db, Model, associations) {
6569
autoFetch : opts.autoFetch || false,
6670
autoFetchLimit : opts.autoFetchLimit || 2,
6771
// I'm not sure the next key is used..
68-
field : util.wrapFieldObject(opts.field, OtherModel, Model.table, OtherModel.properties) || util.formatField(Model, name, true, opts.reversed),
72+
field : util.wrapFieldObject({
73+
field: opts.field, model: OtherModel, altName: Model.table
74+
}) ||
75+
util.formatField(Model, name, true, opts.reversed),
6976
mergeTable : opts.mergeTable || (Model.table + "_" + name),
7077
mergeId : mergeId,
7178
mergeAssocId : mergeAssocId,

lib/Associations/One.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,10 @@ exports.prepare = function (Model, associations) {
3939
if (!association.hasOwnProperty("field")) {
4040
association.field = util.formatField(association.model, association.name, association.required, association.reversed);
4141
} else if(!association.extension) {
42-
association.field = util.wrapFieldObject(association.field, Model, Model.table, Model.properties);
42+
association.field = util.wrapFieldObject({
43+
field: association.field, model: Model, altName: Model.table,
44+
mapsTo: association.mapsTo
45+
});
4346
}
4447

4548
util.convertPropToJoinKeyProp(association.field, {

lib/ORM.js

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -71,12 +71,17 @@ exports.connect = function (opts, cb) {
7171
return ORM_Error(new ORMError("CONNECTION_URL_EMPTY", 'PARAM_MISMATCH'), cb);
7272
}
7373
opts = url.parse(opts, true);
74-
for(var k in opts.query) {
75-
opts[k] = opts.query[k];
76-
}
7774
} else if (typeof opts == 'object') {
7875
opts = _.cloneDeep(opts);
7976
}
77+
78+
opts.query = opts.query || {};
79+
80+
for(var k in opts.query) {
81+
opts.query[k] = queryParamCast(opts.query[k]);
82+
opts[k] = opts.query[k];
83+
}
84+
8085
if (!opts.database) {
8186
// if (!opts.pathname) {
8287
// return cb(new Error("CONNECTION_URL_NO_DATABASE"));
@@ -112,11 +117,9 @@ exports.connect = function (opts, cb) {
112117
try {
113118
var Driver = adapters.get(proto);
114119
var settings = new Settings.Container(exports.settings.get('*'));
115-
var debug = extractOption(opts, "debug");
116-
var pool = extractOption(opts, "pool");
117120
var driver = new Driver(opts, null, {
118-
debug : (debug !== null ? ((debug === "false" || debug === "0") ? false : true) : settings.get("connection.debug")),
119-
pool : (pool !== null ? ((pool === "false" || pool === "0") ? false : true) : settings.get("connection.pool")),
121+
debug : 'debug' in opts.query ? opts.query.debug : settings.get("connection.debug"),
122+
pool : 'pool' in opts.query ? opts.query.pool : settings.get("connection.pool"),
120123
settings : settings
121124
});
122125

@@ -392,19 +395,16 @@ function ORM_Error(err, cb) {
392395
return Emitter;
393396
}
394397

395-
function extractOption(opts, key) {
396-
if (!opts.query || !opts.query.hasOwnProperty(key)) {
397-
return null;
398-
}
399-
400-
var opt = opts.query[key];
401-
402-
delete opts.query[key];
403-
if (opts.href) {
404-
opts.href = opts.href.replace(new RegExp(key + "=[^&]+&?"), "");
405-
}
406-
if (opts.search) {
407-
opts.search = opts.search.replace(new RegExp(key + "=[^&]+&?"), "");
398+
function queryParamCast (val) {
399+
if (typeof val == 'string') {
400+
switch (val) {
401+
case '1':
402+
case 'true':
403+
return true;
404+
case '0':
405+
case 'false':
406+
return false;
407+
}
408408
}
409-
return opt;
409+
return val;
410410
}

lib/Utilities.js

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -158,34 +158,43 @@ exports.getConditions = function (model, fields, from) {
158158
return conditions;
159159
};
160160

161-
exports.wrapFieldObject = function (obj, model, altName, alternatives) {
162-
if (!obj) {
163-
var assoc_key = model.settings.get("properties.association_key");
161+
exports.wrapFieldObject = function (params) {
162+
if (!params.field) {
163+
var assoc_key = params.model.settings.get("properties.association_key");
164164

165165
if (typeof assoc_key === "function") {
166-
obj = assoc_key(altName.toLowerCase(), model.id[0]);
166+
params.field = assoc_key(params.altName.toLowerCase(), params.model.id[0]);
167167
} else {
168-
obj = assoc_key.replace("{name}", altName.toLowerCase())
169-
.replace("{field}", model.id[0]);
168+
params.field = assoc_key.replace("{name}", params.altName.toLowerCase())
169+
.replace("{field}", params.model.id[0]);
170170
}
171171
}
172172

173-
for (var k in obj) {
174-
if (!/[0-9]+/.test(k) && obj.hasOwnProperty(k)) {
175-
return obj;
173+
if (typeof params.field == 'object') {
174+
for (var k in params.field) {
175+
if (!/[0-9]+/.test(k) && params.field.hasOwnProperty(k)) {
176+
return params.field;
177+
}
176178
}
177179
}
178180

179-
var new_obj = {};
181+
var newObj = {}, newProp, propPreDefined, propFromKey;
182+
183+
propPreDefined = params.model.properties[params.field];
184+
propFromKey = params.model.properties[params.model.id[0]];
185+
newProp = { type: 'integer' };
180186

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;
187+
var prop = _.cloneDeep(propPreDefined || propFromKey || newProp);
188+
189+
if (!propPreDefined) {
190+
_.extend(prop, {
191+
name: params.field, mapsTo: params.mapsTo || params.field
192+
});
193+
}
186194

195+
newObj[params.field] = prop;
187196

188-
return new_obj;
197+
return newObj;
189198
};
190199

191200
exports.formatField = function (model, name, required, reversed) {

test/integration/association-hasone.js

Lines changed: 108 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
var ORM = require('../../');
2-
var helper = require('../support/spec_helper');
3-
var should = require('should');
4-
var async = require('async');
5-
var _ = require('lodash');
1+
var ORM = require('../../');
2+
var helper = require('../support/spec_helper');
3+
var should = require('should');
4+
var async = require('async');
5+
var _ = require('lodash');
6+
var common = require('../common');
7+
var protocol = common.protocol();
68

79
describe("hasOne", function() {
810
var db = null;
@@ -12,23 +14,27 @@ describe("hasOne", function() {
1214
var leafId = null;
1315
var treeId = null;
1416
var stalkId = null;
17+
var holeId = null;
1518

1619
var setup = function (opts) {
1720
opts = opts || {};
1821
return function (done) {
1922
db.settings.set('instance.cache', false);
2023
db.settings.set('instance.returnAllErrors', true);
21-
Tree = db.define("tree", { type: { type: 'text' } });
24+
Tree = db.define("tree", { type: { type: 'text' } });
2225
Stalk = db.define("stalk", { length: { type: 'integer' } });
26+
Hole = db.define("hole", { width: { type: 'integer' } });
2327
Leaf = db.define("leaf", {
24-
size: { type: 'integer' }
28+
size: { type: 'integer' },
29+
holeId: { type: 'integer', mapsTo: 'hole_id' }
2530
}, {
2631
validations: opts.validations
2732
});
2833
Leaf.hasOne('tree', Tree, { field: 'treeId', autoFetch: !!opts.autoFetch });
29-
Leaf.hasOne('stalk', Stalk, { field: 'stalkId' });
34+
Leaf.hasOne('stalk', Stalk, { field: 'stalkId', mapsTo: 'stalk_id' });
35+
Leaf.hasOne('hole', Hole, { field: 'holeId' });
3036

31-
return helper.dropSync([Tree, Stalk, Leaf], function() {
37+
return helper.dropSync([Tree, Stalk, Hole, Leaf], function() {
3238
Tree.create({ type: 'pine' }, function (err, tree) {
3339
should.not.exist(err);
3440
treeId = tree[Tree.id];
@@ -41,7 +47,11 @@ describe("hasOne", function() {
4147
should.not.exist(err);
4248
should.exist(stalk);
4349
stalkId = stalk[Stalk.id];
44-
done();
50+
Hole.create({ width: 3 }, function (err, hole) {
51+
should.not.exist(err);
52+
holeId = hole.id;
53+
done();
54+
});
4555
});
4656
});
4757
});
@@ -370,4 +380,92 @@ describe("hasOne", function() {
370380
return done();
371381
});
372382
});
383+
384+
if (protocol != "mongodb") {
385+
describe("mapsTo", function () {
386+
describe("with `mapsTo` set via `hasOne`", function () {
387+
var leaf = null;
388+
389+
before(setup());
390+
391+
before(function (done) {
392+
Leaf.create({ size: 444, stalkId: stalkId, holeId: holeId }, function (err, lf) {
393+
should.not.exist(err);
394+
leaf = lf;
395+
done();
396+
});
397+
});
398+
399+
it("should have correct fields in the DB", function (done) {
400+
var sql = db.driver.query.select()
401+
.from('leaf')
402+
.select('size', 'stalk_id')
403+
.where({ size: 444 })
404+
.build();
405+
406+
db.driver.execQuery(sql, function (err, rows) {
407+
should.not.exist(err);
408+
409+
should.equal(rows[0].size, 444);
410+
should.equal(rows[0].stalk_id, 1);
411+
412+
done();
413+
});
414+
});
415+
416+
it("should get parent", function (done) {
417+
leaf.getStalk(function (err, stalk) {
418+
should.not.exist(err);
419+
420+
should.exist(stalk);
421+
should.equal(stalk.id, stalkId);
422+
should.equal(stalk.length, 20);
423+
done();
424+
});
425+
});
426+
});
427+
428+
describe("with `mapsTo` set via property definition", function () {
429+
var leaf = null;
430+
431+
before(setup());
432+
433+
before(function (done) {
434+
Leaf.create({ size: 444, stalkId: stalkId, holeId: holeId }, function (err, lf) {
435+
should.not.exist(err);
436+
leaf = lf;
437+
done();
438+
});
439+
});
440+
441+
it("should have correct fields in the DB", function (done) {
442+
var sql = db.driver.query.select()
443+
.from('leaf')
444+
.select('size', 'hole_id')
445+
.where({ size: 444 })
446+
.build();
447+
448+
db.driver.execQuery(sql, function (err, rows) {
449+
should.not.exist(err);
450+
451+
should.equal(rows[0].size, 444);
452+
should.equal(rows[0].hole_id, 1);
453+
454+
done();
455+
});
456+
});
457+
458+
it("should get parent", function (done) {
459+
leaf.getHole(function (err, hole) {
460+
should.not.exist(err);
461+
462+
should.exist(hole);
463+
should.equal(hole.id, stalkId);
464+
should.equal(hole.width, 3);
465+
done();
466+
});
467+
});
468+
});
469+
});
470+
};
373471
});

0 commit comments

Comments
 (0)