primaryKey for hasMany and belongsTo relations

This commit is contained in:
sklyukin 2015-09-01 01:24:47 +05:00
parent 483cd873e7
commit d0f9b760f5
2 changed files with 115 additions and 18 deletions

View File

@ -588,7 +588,7 @@ RelationDefinition.hasMany = function hasMany(modelFrom, modelTo, params) {
var fk = params.foreignKey || i8n.camelize(thisClassName + '_id', true);
var keyThrough = params.keyThrough || i8n.camelize(modelTo.modelName + '_id', true);
var idName = modelFrom.dataSource.idName(modelFrom.modelName) || 'id';
var pkName = params.primaryKey || modelFrom.dataSource.idName(modelFrom.modelName) || 'id';
var discriminator, polymorphic;
if (params.polymorphic) {
@ -610,7 +610,7 @@ RelationDefinition.hasMany = function hasMany(modelFrom, modelTo, params) {
name: relationName,
type: RelationTypes.hasMany,
modelFrom: modelFrom,
keyFrom: idName,
keyFrom: pkName,
keyTo: fk,
modelTo: modelTo,
multiple: true,
@ -629,7 +629,7 @@ RelationDefinition.hasMany = function hasMany(modelFrom, modelTo, params) {
// obviously, modelTo should have attribute called `fk`
// for polymorphic relations, it is assumed to share the same fk type for all
// polymorphic models
modelTo.dataSource.defineForeignKey(modelTo.modelName, fk, modelFrom.modelName);
modelTo.dataSource.defineForeignKey(modelTo.modelName, fk, modelFrom.modelName, pkName);
}
var scopeMethods = {
@ -680,7 +680,7 @@ RelationDefinition.hasMany = function hasMany(modelFrom, modelTo, params) {
defineScope(modelFrom.prototype, params.through || modelTo, relationName, function () {
var filter = {};
filter.where = {};
filter.where[fk] = this[idName];
filter.where[fk] = this[pkName];
definition.applyScope(this, filter);
@ -1216,7 +1216,7 @@ RelationDefinition.belongsTo = function (modelFrom, modelTo, params) {
modelTo = lookupModelTo(modelFrom, modelTo, params);
}
var idName, relationName, fk;
var pkName, relationName, fk;
if (params.polymorphic) {
relationName = params.as || (typeof modelTo === 'string' ? modelTo : null); // initially
@ -1229,7 +1229,7 @@ RelationDefinition.belongsTo = function (modelFrom, modelTo, params) {
modelTo = null; // will lookup dynamically
idName = params.idName || 'id';
pkName = params.primaryKey || params.idName || 'id';
relationName = params.as || polymorphic.as; // finally
fk = polymorphic.foreignKey;
discriminator = polymorphic.discriminator;
@ -1237,16 +1237,16 @@ RelationDefinition.belongsTo = function (modelFrom, modelTo, params) {
if (polymorphic.idType) { // explicit key type
modelFrom.dataSource.defineProperty(modelFrom.modelName, fk, { type: polymorphic.idType, index: true });
} else { // try to use the same foreign key type as modelFrom
modelFrom.dataSource.defineForeignKey(modelFrom.modelName, fk, modelFrom.modelName);
modelFrom.dataSource.defineForeignKey(modelFrom.modelName, fk, modelFrom.modelName, pkName);
}
modelFrom.dataSource.defineProperty(modelFrom.modelName, discriminator, { type: 'string', index: true });
} else {
idName = modelTo.dataSource.idName(modelTo.modelName) || 'id';
pkName = params.primaryKey || modelTo.dataSource.idName(modelTo.modelName) || 'id';
relationName = params.as || i8n.camelize(modelTo.modelName, true);
fk = params.foreignKey || relationName + 'Id';
modelFrom.dataSource.defineForeignKey(modelFrom.modelName, fk, modelTo.modelName);
modelFrom.dataSource.defineForeignKey(modelFrom.modelName, fk, modelTo.modelName, pkName);
}
var definition = modelFrom.relations[relationName] = new RelationDefinition({
@ -1254,7 +1254,7 @@ RelationDefinition.belongsTo = function (modelFrom, modelTo, params) {
type: RelationTypes.belongsTo,
modelFrom: modelFrom,
keyFrom: fk,
keyTo: idName,
keyTo: pkName,
modelTo: modelTo,
multiple: false,
properties: params.properties,

View File

@ -3113,7 +3113,7 @@ describe('relations', function () {
Boss = db.define('Boss', {boardMembersNumber: Number, companyId: String});
});
it('can be declared with non standard foreignKey', function () {
it('relation can be declared with primaryKey', function () {
CompanyBoard.hasOne(Boss, {
properties: {membersNumber: 'boardMembersNumber'},
primaryKey: 'companyId',
@ -3124,7 +3124,7 @@ describe('relations', function () {
});
it('can be used to query data', function (done) {
db.automigrate(function () {
db.automigrate(['CompanyBoard', 'Boss'],function () {
CompanyBoard.create({membersNumber: 7, companyId: 'Company1'}, function (e, companyBoard) {
companyBoardId = companyBoard.id;
should.not.exist(e);
@ -3145,22 +3145,22 @@ describe('relations', function () {
});
});
it('should destroy the related item on scope', function(done) {
CompanyBoard.findById(companyBoardId, function(e, companyBoard) {
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) {
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) {
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) {
companyBoard.boss(function (err, act) {
should.not.exist(e);
should.not.exist(act);
done();
@ -3169,6 +3169,103 @@ describe('relations', function () {
});
});
describe('hasMany with primaryKey different from model PK', function () {
var Employee, Boss;
var COMPANY_ID = "Company1";
before(function () {
db = getSchema();
Employee = db.define('Employee', {name: String, companyId: String});
Boss = db.define('Boss', {address: String, companyId: String});
});
it('relation can be declared with primaryKey', function () {
Boss.hasMany(Employee, {
primaryKey: 'companyId',
foreignKey: 'companyId'
});
(new Boss()).employees.should.be.an.instanceOf(Function);
});
it('can be used to query employees for boss', function () {
return db.automigrate(['Employee', 'Boss']).then(function () {
return Boss.create({address: 'testAddress', companyId: COMPANY_ID})
.then(function (boss) {
should.exist(boss);
should.exist(boss.employees);
return boss.employees.create([{name: 'a01'}, {name: 'a02'}])
.then(function (employees) {
should.exists(employees);
return boss.employees();
}).then(function (employees) {
var employee = employees[0];
should.exist(employee);
employees.length.should.equal(2);
employee.should.be.an.instanceOf(Employee);
employee.companyId.should.be.equal(boss.companyId);
return employees;
})
});
});
});
it('can be used to query employees for boss2', function () {
return db.automigrate(['Employee', 'Boss']).then(function () {
return Boss.create({address: 'testAddress', companyId: COMPANY_ID})
.then(function (boss) {
return Employee.create({name: 'a01', companyId: COMPANY_ID})
.then(function (employee) {
should.exist(employee);
return boss.employees.getAsync();
}).then(function (employees) {
should.exists(employees);
employees.length.should.equal(1);
})
});
});
});
});
describe('belongsTo with primaryKey different from model PK', function () {
var Employee, Boss;
var COMPANY_ID = "Company1";
var bossId;
before(function () {
db = getSchema();
Employee = db.define('Employee', {name: String, companyId: String});
Boss = db.define('Boss', {address: String, companyId: String});
});
it('relation can be declared with primaryKey', function () {
Employee.belongsTo(Boss, {
primaryKey: 'companyId',
foreignKey: 'companyId'
});
(new Employee()).boss.should.be.an.instanceOf(Function);
});
it('can be used to query data', function () {
return db.automigrate(['Employee', 'Boss']).then(function () {
return Boss.create({address: 'testAddress', companyId: COMPANY_ID})
.then(function (boss) {
bossId = boss.id;
return Employee.create({name: 'a', companyId: COMPANY_ID})
})
.then(function (employee) {
should.exists(employee);
return employee.boss.getAsync();
})
.then(function (boss) {
should.exists(boss);
boss.id.should.equal(bossId);
});
});
});
});
describe('hasAndBelongsToMany', function () {
var Article, TagName, ArticleTag;
it('can be declared', function (done) {