Merge pull request #687 from sklyukin/master
primaryKey to hasOne relation
This commit is contained in:
commit
207edd5eec
|
@ -1796,11 +1796,12 @@ DataSource.prototype.idProperty = function (modelName) {
|
||||||
* @param {String} className The model name that owns the key
|
* @param {String} className The model name that owns the key
|
||||||
* @param {String} key Name of key field
|
* @param {String} key Name of key field
|
||||||
* @param {String} foreignClassName The foreign model name
|
* @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 pkType = null;
|
||||||
var foreignModel = this.getModelDefinition(foreignClassName);
|
var foreignModel = this.getModelDefinition(foreignClassName);
|
||||||
var pkName = foreignModel && foreignModel.idName();
|
pkName = pkName || foreignModel && foreignModel.idName();
|
||||||
if (pkName) {
|
if (pkName) {
|
||||||
pkType = foreignModel.properties[pkName].type;
|
pkType = foreignModel.properties[pkName].type;
|
||||||
}
|
}
|
||||||
|
|
|
@ -588,7 +588,7 @@ RelationDefinition.hasMany = function hasMany(modelFrom, modelTo, params) {
|
||||||
var fk = params.foreignKey || i8n.camelize(thisClassName + '_id', true);
|
var fk = params.foreignKey || i8n.camelize(thisClassName + '_id', true);
|
||||||
var keyThrough = params.keyThrough || i8n.camelize(modelTo.modelName + '_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;
|
var discriminator, polymorphic;
|
||||||
|
|
||||||
if (params.polymorphic) {
|
if (params.polymorphic) {
|
||||||
|
@ -610,7 +610,7 @@ RelationDefinition.hasMany = function hasMany(modelFrom, modelTo, params) {
|
||||||
name: relationName,
|
name: relationName,
|
||||||
type: RelationTypes.hasMany,
|
type: RelationTypes.hasMany,
|
||||||
modelFrom: modelFrom,
|
modelFrom: modelFrom,
|
||||||
keyFrom: idName,
|
keyFrom: pkName,
|
||||||
keyTo: fk,
|
keyTo: fk,
|
||||||
modelTo: modelTo,
|
modelTo: modelTo,
|
||||||
multiple: true,
|
multiple: true,
|
||||||
|
@ -629,7 +629,7 @@ RelationDefinition.hasMany = function hasMany(modelFrom, modelTo, params) {
|
||||||
// obviously, modelTo should have attribute called `fk`
|
// obviously, modelTo should have attribute called `fk`
|
||||||
// for polymorphic relations, it is assumed to share the same fk type for all
|
// for polymorphic relations, it is assumed to share the same fk type for all
|
||||||
// polymorphic models
|
// polymorphic models
|
||||||
modelTo.dataSource.defineForeignKey(modelTo.modelName, fk, modelFrom.modelName);
|
modelTo.dataSource.defineForeignKey(modelTo.modelName, fk, modelFrom.modelName, pkName);
|
||||||
}
|
}
|
||||||
|
|
||||||
var scopeMethods = {
|
var scopeMethods = {
|
||||||
|
@ -680,7 +680,7 @@ RelationDefinition.hasMany = function hasMany(modelFrom, modelTo, params) {
|
||||||
defineScope(modelFrom.prototype, params.through || modelTo, relationName, function () {
|
defineScope(modelFrom.prototype, params.through || modelTo, relationName, function () {
|
||||||
var filter = {};
|
var filter = {};
|
||||||
filter.where = {};
|
filter.where = {};
|
||||||
filter.where[fk] = this[idName];
|
filter.where[fk] = this[pkName];
|
||||||
|
|
||||||
definition.applyScope(this, filter);
|
definition.applyScope(this, filter);
|
||||||
|
|
||||||
|
@ -1216,7 +1216,7 @@ RelationDefinition.belongsTo = function (modelFrom, modelTo, params) {
|
||||||
modelTo = lookupModelTo(modelFrom, modelTo, params);
|
modelTo = lookupModelTo(modelFrom, modelTo, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
var idName, relationName, fk;
|
var pkName, relationName, fk;
|
||||||
if (params.polymorphic) {
|
if (params.polymorphic) {
|
||||||
relationName = params.as || (typeof modelTo === 'string' ? modelTo : null); // initially
|
relationName = params.as || (typeof modelTo === 'string' ? modelTo : null); // initially
|
||||||
|
|
||||||
|
@ -1229,7 +1229,7 @@ RelationDefinition.belongsTo = function (modelFrom, modelTo, params) {
|
||||||
|
|
||||||
modelTo = null; // will lookup dynamically
|
modelTo = null; // will lookup dynamically
|
||||||
|
|
||||||
idName = params.idName || 'id';
|
pkName = params.primaryKey || params.idName || 'id';
|
||||||
relationName = params.as || polymorphic.as; // finally
|
relationName = params.as || polymorphic.as; // finally
|
||||||
fk = polymorphic.foreignKey;
|
fk = polymorphic.foreignKey;
|
||||||
discriminator = polymorphic.discriminator;
|
discriminator = polymorphic.discriminator;
|
||||||
|
@ -1237,16 +1237,16 @@ RelationDefinition.belongsTo = function (modelFrom, modelTo, params) {
|
||||||
if (polymorphic.idType) { // explicit key type
|
if (polymorphic.idType) { // explicit key type
|
||||||
modelFrom.dataSource.defineProperty(modelFrom.modelName, fk, { type: polymorphic.idType, index: true });
|
modelFrom.dataSource.defineProperty(modelFrom.modelName, fk, { type: polymorphic.idType, index: true });
|
||||||
} else { // try to use the same foreign key type as modelFrom
|
} 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 });
|
modelFrom.dataSource.defineProperty(modelFrom.modelName, discriminator, { type: 'string', index: true });
|
||||||
} else {
|
} 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);
|
relationName = params.as || i8n.camelize(modelTo.modelName, true);
|
||||||
fk = params.foreignKey || relationName + 'Id';
|
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({
|
var definition = modelFrom.relations[relationName] = new RelationDefinition({
|
||||||
|
@ -1254,7 +1254,7 @@ RelationDefinition.belongsTo = function (modelFrom, modelTo, params) {
|
||||||
type: RelationTypes.belongsTo,
|
type: RelationTypes.belongsTo,
|
||||||
modelFrom: modelFrom,
|
modelFrom: modelFrom,
|
||||||
keyFrom: fk,
|
keyFrom: fk,
|
||||||
keyTo: idName,
|
keyTo: pkName,
|
||||||
modelTo: modelTo,
|
modelTo: modelTo,
|
||||||
multiple: false,
|
multiple: false,
|
||||||
properties: params.properties,
|
properties: params.properties,
|
||||||
|
@ -1600,7 +1600,7 @@ RelationDefinition.hasOne = function (modelFrom, modelTo, params) {
|
||||||
params = params || {};
|
params = params || {};
|
||||||
modelTo = lookupModelTo(modelFrom, modelTo, 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 relationName = params.as || i8n.camelize(modelTo.modelName, true);
|
||||||
|
|
||||||
var fk = params.foreignKey || i8n.camelize(modelFrom.modelName + '_id', true);
|
var fk = params.foreignKey || i8n.camelize(modelFrom.modelName + '_id', true);
|
||||||
|
@ -1630,7 +1630,7 @@ RelationDefinition.hasOne = function (modelFrom, modelTo, params) {
|
||||||
methods: params.methods
|
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
|
// Define a property for the scope so that we have 'this' for the scoped methods
|
||||||
Object.defineProperty(modelFrom.prototype, relationName, {
|
Object.defineProperty(modelFrom.prototype, relationName, {
|
||||||
|
|
|
@ -3103,6 +3103,169 @@ 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('relation can be declared with primaryKey', 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(['CompanyBoard', 'Boss'],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('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 () {
|
describe('hasAndBelongsToMany', function () {
|
||||||
var Article, TagName, ArticleTag;
|
var Article, TagName, ArticleTag;
|
||||||
it('can be declared', function (done) {
|
it('can be declared', function (done) {
|
||||||
|
|
Loading…
Reference in New Issue