diff --git a/lib/datasource.js b/lib/datasource.js index 97ce57c2..ef0bd4e6 100644 --- a/lib/datasource.js +++ b/lib/datasource.js @@ -1796,11 +1796,12 @@ DataSource.prototype.idProperty = function (modelName) { * @param {String} className The model name that owns the key * @param {String} key Name of key field * @param {String} foreignClassName The foreign model name + * @param {String} pkName (optional) primary key used for foreignKey */ -DataSource.prototype.defineForeignKey = function defineForeignKey(className, key, foreignClassName) { +DataSource.prototype.defineForeignKey = function defineForeignKey(className, key, foreignClassName, pkName) { var pkType = null; var foreignModel = this.getModelDefinition(foreignClassName); - var pkName = foreignModel && foreignModel.idName(); + pkName = pkName || foreignModel && foreignModel.idName(); if (pkName) { pkType = foreignModel.properties[pkName].type; } diff --git a/lib/relation-definition.js b/lib/relation-definition.js index 48c8254a..98f61b39 100644 --- a/lib/relation-definition.js +++ b/lib/relation-definition.js @@ -1600,7 +1600,7 @@ RelationDefinition.hasOne = function (modelFrom, modelTo, params) { params = params || {}; modelTo = lookupModelTo(modelFrom, modelTo, params); - var pk = modelFrom.dataSource.idName(modelFrom.modelName) || 'id'; + var pk = params.primaryKey || modelFrom.dataSource.idName(modelFrom.modelName) || 'id'; var relationName = params.as || i8n.camelize(modelTo.modelName, true); var fk = params.foreignKey || i8n.camelize(modelFrom.modelName + '_id', true); @@ -1630,7 +1630,7 @@ RelationDefinition.hasOne = function (modelFrom, modelTo, params) { methods: params.methods }); - modelTo.dataSource.defineForeignKey(modelTo.modelName, fk, modelFrom.modelName); + modelTo.dataSource.defineForeignKey(modelTo.modelName, fk, modelFrom.modelName, pk); // Define a property for the scope so that we have 'this' for the scoped methods Object.defineProperty(modelFrom.prototype, relationName, { diff --git a/test/relations.test.js b/test/relations.test.js index 0810344e..f0b548e7 100644 --- a/test/relations.test.js +++ b/test/relations.test.js @@ -3103,6 +3103,72 @@ describe('relations', function () { }); + describe('hasOne with primaryKey different from model PK', function () { + var CompanyBoard, Boss; + var companyBoardId, bossId; + + before(function () { + db = getSchema(); + CompanyBoard = db.define('CompanyBoard', {membersNumber: Number, companyId: String}); + Boss = db.define('Boss', {boardMembersNumber: Number, companyId: String}); + }); + + it('can be declared with non standard foreignKey', function () { + CompanyBoard.hasOne(Boss, { + properties: {membersNumber: 'boardMembersNumber'}, + primaryKey: 'companyId', + foreignKey: 'companyId' + }); + Object.keys((new Boss()).toObject()).should.containEql('companyId'); + (new CompanyBoard()).boss.should.be.an.instanceOf(Function); + }); + + it('can be used to query data', function (done) { + db.automigrate(function () { + CompanyBoard.create({membersNumber: 7, companyId: 'Company1'}, function (e, companyBoard) { + companyBoardId = companyBoard.id; + should.not.exist(e); + should.exist(companyBoard); + companyBoard.boss.create({id: 'a01'}, function (err, account) { + companyBoard.boss(function (e, boss) { + bossId = boss.id; + should.not.exist(e); + should.exist(boss); + boss.should.be.an.instanceOf(Boss); + companyBoard.boss().id.should.equal(boss.id); + boss.boardMembersNumber.should.equal(companyBoard.membersNumber); + boss.companyId.should.equal(companyBoard.companyId); + done(); + }); + }); + }); + }); + }); + + it('should destroy the related item on scope', function(done) { + CompanyBoard.findById(companyBoardId, function(e, companyBoard) { + should.not.exist(e); + should.exist(companyBoard); + companyBoard.boss.destroy(function(err) { + should.not.exist(e); + done(); + }); + }); + }); + + it('should get the related item on scope - verify', function(done) { + CompanyBoard.findById(companyBoardId, function(e, companyBoard) { + should.not.exist(e); + should.exist(companyBoard); + companyBoard.boss(function(err, act) { + should.not.exist(e); + should.not.exist(act); + done(); + }); + }); + }); + }); + describe('hasAndBelongsToMany', function () { var Article, TagName, ArticleTag; it('can be declared', function (done) {