Skip to content

Commit

Permalink
Add 'mapsTo' option when defining hasOne #638
Browse files Browse the repository at this point in the history
  • Loading branch information
dxg committed May 12, 2015
1 parent b8497fb commit 5dfbe1c
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 26 deletions.
4 changes: 3 additions & 1 deletion lib/Associations/Extend.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ exports.prepare = function (db, Model, associations) {
reversed : opts.reversed,
autoFetch : opts.autoFetch || false,
autoFetchLimit : opts.autoFetchLimit || 2,
field : util.wrapFieldObject(opts.field, Model, Model.table, Model.properties) || util.formatField(Model, Model.table, false, false),
field : util.wrapFieldObject({
field: opts.field, model: Model, altName: Model.table
}) || util.formatField(Model, Model.table, false, false),
getAccessor : opts.getAccessor || ("get" + assocName),
setAccessor : opts.setAccessor || ("set" + assocName),
hasAccessor : opts.hasAccessor || ("has" + assocName),
Expand Down
13 changes: 10 additions & 3 deletions lib/Associations/Many.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,17 @@ exports.prepare = function (db, Model, associations) {
makeKey = opts.key || Settings.defaults().hasMany.key;

mergeId = util.convertPropToJoinKeyProp(
util.wrapFieldObject(opts.mergeId, Model, Model.table, Model.properties) ||
util.wrapFieldObject({
field: opts.mergeId, model: Model, altName: Model.table
}) ||
util.formatField(Model, Model.table, true, opts.reversed),
{ makeKey: makeKey, required: true }
);

mergeAssocId = util.convertPropToJoinKeyProp(
util.wrapFieldObject(opts.mergeAssocId, OtherModel, name, OtherModel.properties) ||
util.wrapFieldObject({
field: opts.mergeAssocId, model: OtherModel, altName: name
}) ||
util.formatField(OtherModel, name, true, opts.reversed),
{ makeKey: makeKey, required: true }
)
Expand All @@ -65,7 +69,10 @@ exports.prepare = function (db, Model, associations) {
autoFetch : opts.autoFetch || false,
autoFetchLimit : opts.autoFetchLimit || 2,
// I'm not sure the next key is used..
field : util.wrapFieldObject(opts.field, OtherModel, Model.table, OtherModel.properties) || util.formatField(Model, name, true, opts.reversed),
field : util.wrapFieldObject({
field: opts.field, model: OtherModel, altName: Model.table
}) ||
util.formatField(Model, name, true, opts.reversed),
mergeTable : opts.mergeTable || (Model.table + "_" + name),
mergeId : mergeId,
mergeAssocId : mergeAssocId,
Expand Down
5 changes: 4 additions & 1 deletion lib/Associations/One.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,10 @@ exports.prepare = function (Model, associations) {
if (!association.hasOwnProperty("field")) {
association.field = util.formatField(association.model, association.name, association.required, association.reversed);
} else if(!association.extension) {
association.field = util.wrapFieldObject(association.field, Model, Model.table, Model.properties);
association.field = util.wrapFieldObject({
field: association.field, model: Model, altName: Model.table,
mapsTo: association.mapsTo
});
}

util.convertPropToJoinKeyProp(association.field, {
Expand Down
41 changes: 25 additions & 16 deletions lib/Utilities.js
Original file line number Diff line number Diff line change
Expand Up @@ -158,34 +158,43 @@ exports.getConditions = function (model, fields, from) {
return conditions;
};

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

if (typeof assoc_key === "function") {
obj = assoc_key(altName.toLowerCase(), model.id[0]);
params.field = assoc_key(params.altName.toLowerCase(), params.model.id[0]);
} else {
obj = assoc_key.replace("{name}", altName.toLowerCase())
.replace("{field}", model.id[0]);
params.field = assoc_key.replace("{name}", params.altName.toLowerCase())
.replace("{field}", params.model.id[0]);
}
}

for (var k in obj) {
if (!/[0-9]+/.test(k) && obj.hasOwnProperty(k)) {
return obj;
if (typeof params.field == 'object') {
for (var k in params.field) {
if (!/[0-9]+/.test(k) && params.field.hasOwnProperty(k)) {
return params.field;
}
}
}

var new_obj = {};
var newObj = {}, newProp, propPreDefined, propFromKey;

propPreDefined = params.model.properties[params.field];
propFromKey = params.model.properties[params.model.id[0]];
newProp = { type: 'integer' };

new_obj[obj] = _.cloneDeep(
alternatives[obj] || alternatives[model.id[0]] || { type: 'number', unsigned: true, rational: false }
);
new_obj[obj].name = obj;
new_obj[obj].mapsTo = obj;
var prop = _.cloneDeep(propPreDefined || propFromKey || newProp);

if (!propPreDefined) {
_.extend(prop, {
name: params.field, mapsTo: params.mapsTo || params.field
});
}

newObj[params.field] = prop;

return new_obj;
return newObj;
};

exports.formatField = function (model, name, required, reversed) {
Expand Down
104 changes: 99 additions & 5 deletions test/integration/association-hasone.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,27 @@ describe("hasOne", function() {
var leafId = null;
var treeId = null;
var stalkId = null;
var holeId = null;

var setup = function (opts) {
opts = opts || {};
return function (done) {
db.settings.set('instance.cache', false);
db.settings.set('instance.returnAllErrors', true);
Tree = db.define("tree", { type: { type: 'text' } });
Tree = db.define("tree", { type: { type: 'text' } });
Stalk = db.define("stalk", { length: { type: 'integer' } });
Hole = db.define("hole", { width: { type: 'integer' } });
Leaf = db.define("leaf", {
size: { type: 'integer' }
size: { type: 'integer' },
holeId: { type: 'integer', mapsTo: 'hole_id' }
}, {
validations: opts.validations
});
Leaf.hasOne('tree', Tree, { field: 'treeId', autoFetch: !!opts.autoFetch });
Leaf.hasOne('stalk', Stalk, { field: 'stalkId' });
Leaf.hasOne('stalk', Stalk, { field: 'stalkId', mapsTo: 'stalk_id' });
Leaf.hasOne('hole', Hole, { field: 'holeId' });

return helper.dropSync([Tree, Stalk, Leaf], function() {
return helper.dropSync([Tree, Stalk, Hole, Leaf], function() {
Tree.create({ type: 'pine' }, function (err, tree) {
should.not.exist(err);
treeId = tree[Tree.id];
Expand All @@ -41,7 +45,11 @@ describe("hasOne", function() {
should.not.exist(err);
should.exist(stalk);
stalkId = stalk[Stalk.id];
done();
Hole.create({ width: 3 }, function (err, hole) {
should.not.exist(err);
holeId = hole.id;
done();
});
});
});
});
Expand Down Expand Up @@ -370,4 +378,90 @@ describe("hasOne", function() {
return done();
});
});

describe("mapsTo", function () {
describe("with `mapsTo` set via `hasOne`", function () {
var leaf = null;

before(setup());

before(function (done) {
Leaf.create({ size: 444, stalkId: stalkId, holeId: holeId }, function (err, lf) {
should.not.exist(err);
leaf = lf;
done();
});
});

it("should have correct fields in the DB", function (done) {
var sql = db.driver.query.select()
.from('leaf')
.select('size', 'stalk_id')
.where({ size: 444 })
.build();

db.driver.execQuery(sql, function (err, rows) {
should.not.exist(err);

should.equal(rows[0].size, 444);
should.equal(rows[0].stalk_id, 1);

done();
});
});

it("should get parent", function (done) {
leaf.getStalk(function (err, stalk) {
should.not.exist(err);

should.exist(stalk);
should.equal(stalk.id, stalkId);
should.equal(stalk.length, 20);
done();
});
});
});

describe("with `mapsTo` set via property definition", function () {
var leaf = null;

before(setup());

before(function (done) {
Leaf.create({ size: 444, stalkId: stalkId, holeId: holeId }, function (err, lf) {
should.not.exist(err);
leaf = lf;
done();
});
});

it("should have correct fields in the DB", function (done) {
var sql = db.driver.query.select()
.from('leaf')
.select('size', 'hole_id')
.where({ size: 444 })
.build();

db.driver.execQuery(sql, function (err, rows) {
should.not.exist(err);

should.equal(rows[0].size, 444);
should.equal(rows[0].hole_id, 1);

done();
});
});

it("should get parent", function (done) {
leaf.getHole(function (err, hole) {
should.not.exist(err);

should.exist(hole);
should.equal(hole.id, stalkId);
should.equal(hole.width, 3);
done();
});
});
});
});
});

0 comments on commit 5dfbe1c

Please sign in to comment.