Merge pull request #286 from fabien/fix/polymorphic-transient
getTransientDataSource helper + embedsMany/polymorphic test case fix
This commit is contained in:
commit
5c7a9aee3a
|
@ -391,13 +391,13 @@ util.inherits(HasOne, Relation);
|
||||||
* EmbedsOne subclass
|
* EmbedsOne subclass
|
||||||
* @param {RelationDefinition|Object} definition
|
* @param {RelationDefinition|Object} definition
|
||||||
* @param {Object} modelInstance
|
* @param {Object} modelInstance
|
||||||
* @returns {EmbedsMany}
|
* @returns {EmbedsOne}
|
||||||
* @constructor
|
* @constructor
|
||||||
* @class EmbedsOne
|
* @class EmbedsOne
|
||||||
*/
|
*/
|
||||||
function EmbedsOne(definition, modelInstance) {
|
function EmbedsOne(definition, modelInstance) {
|
||||||
if (!(this instanceof EmbedsOne)) {
|
if (!(this instanceof EmbedsOne)) {
|
||||||
return new EmbedsMany(definition, modelInstance);
|
return new EmbedsOne(definition, modelInstance);
|
||||||
}
|
}
|
||||||
assert(definition.type === RelationTypes.embedsOne);
|
assert(definition.type === RelationTypes.embedsOne);
|
||||||
Relation.apply(this, arguments);
|
Relation.apply(this, arguments);
|
||||||
|
@ -503,9 +503,9 @@ function lookupModelTo(modelFrom, modelTo, params, singularize) {
|
||||||
* @param {Object|String} params Name of the polymorphic relation or params
|
* @param {Object|String} params Name of the polymorphic relation or params
|
||||||
* @returns {Object} The normalized parameters
|
* @returns {Object} The normalized parameters
|
||||||
*/
|
*/
|
||||||
function polymorphicParams(params) {
|
function polymorphicParams(params, as) {
|
||||||
if (typeof params === 'string') params = { as: params };
|
if (typeof params === 'string') params = { as: params };
|
||||||
if (typeof params.as !== 'string') params.as = 'reference'; // default
|
if (typeof params.as !== 'string') params.as = as || 'reference'; // default
|
||||||
params.foreignKey = params.foreignKey || i8n.camelize(params.as + '_id', true);
|
params.foreignKey = params.foreignKey || i8n.camelize(params.as + '_id', true);
|
||||||
params.discriminator = params.discriminator || i8n.camelize(params.as + '_type', true);
|
params.discriminator = params.discriminator || i8n.camelize(params.as + '_type', true);
|
||||||
return params;
|
return params;
|
||||||
|
@ -1079,21 +1079,23 @@ RelationDefinition.belongsTo = function (modelFrom, modelTo, params) {
|
||||||
|
|
||||||
var idName, relationName, fk;
|
var idName, relationName, fk;
|
||||||
if (params.polymorphic) {
|
if (params.polymorphic) {
|
||||||
|
relationName = params.as || (typeof modelTo === 'string' ? modelTo : null); // initially
|
||||||
|
|
||||||
if (params.polymorphic === true) {
|
if (params.polymorphic === true) {
|
||||||
// modelTo arg will be the name of the polymorphic relation (string)
|
// modelTo arg will be the name of the polymorphic relation (string)
|
||||||
polymorphic = polymorphicParams(modelTo);
|
polymorphic = polymorphicParams(modelTo, relationName);
|
||||||
} else {
|
} else {
|
||||||
polymorphic = polymorphicParams(params.polymorphic);
|
polymorphic = polymorphicParams(params.polymorphic, relationName);
|
||||||
}
|
}
|
||||||
|
|
||||||
modelTo = null; // will lookup dynamically
|
modelTo = null; // will lookup dynamically
|
||||||
|
|
||||||
idName = params.idName || 'id';
|
idName = params.idName || 'id';
|
||||||
relationName = params.as || polymorphic.as;
|
relationName = params.as || polymorphic.as; // finally
|
||||||
fk = polymorphic.foreignKey;
|
fk = polymorphic.foreignKey;
|
||||||
discriminator = polymorphic.discriminator;
|
discriminator = polymorphic.discriminator;
|
||||||
|
|
||||||
if (typeof polymorphic.idType === 'string') { // 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);
|
||||||
|
@ -2208,10 +2210,7 @@ EmbedsMany.prototype.build = function(targetModelData) {
|
||||||
|
|
||||||
var assignId = (forceId || targetModelData[pk] === undefined);
|
var assignId = (forceId || targetModelData[pk] === undefined);
|
||||||
|
|
||||||
if (assignId && typeof connector.generateId === 'function') {
|
if (assignId && pkType === Number) {
|
||||||
var id = connector.generateId(modelTo.modelName, targetModelData, pk);
|
|
||||||
targetModelData[pk] = id;
|
|
||||||
} else if (assignId && pkType === Number) {
|
|
||||||
var ids = embeddedList.map(function(m) {
|
var ids = embeddedList.map(function(m) {
|
||||||
return (typeof m[pk] === 'number' ? m[pk] : 0);
|
return (typeof m[pk] === 'number' ? m[pk] : 0);
|
||||||
});
|
});
|
||||||
|
@ -2220,6 +2219,9 @@ EmbedsMany.prototype.build = function(targetModelData) {
|
||||||
} else {
|
} else {
|
||||||
targetModelData[pk] = 1;
|
targetModelData[pk] = 1;
|
||||||
}
|
}
|
||||||
|
} else if (assignId && typeof connector.generateId === 'function') {
|
||||||
|
var id = connector.generateId(modelTo.modelName, targetModelData, pk);
|
||||||
|
targetModelData[pk] = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.definition.applyProperties(modelInstance, targetModelData);
|
this.definition.applyProperties(modelInstance, targetModelData);
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
// This test written in mocha+should.js
|
// This test written in mocha+should.js
|
||||||
var should = require('./init.js');
|
var should = require('./init.js');
|
||||||
|
var jdb = require('../');
|
||||||
|
var DataSource = jdb.DataSource;
|
||||||
|
|
||||||
var db, tmp, Book, Chapter, Author, Reader;
|
var db, tmp, Book, Chapter, Author, Reader;
|
||||||
var Category, Job;
|
var Category, Job;
|
||||||
|
@ -7,6 +9,10 @@ var Picture, PictureLink;
|
||||||
var Person, Address;
|
var Person, Address;
|
||||||
var Link;
|
var Link;
|
||||||
|
|
||||||
|
var getTransientDataSource = function(settings) {
|
||||||
|
return new DataSource('transient', settings, db.modelBuilder);
|
||||||
|
};
|
||||||
|
|
||||||
describe('relations', function () {
|
describe('relations', function () {
|
||||||
|
|
||||||
describe('hasMany', function () {
|
describe('hasMany', function () {
|
||||||
|
@ -1679,7 +1685,7 @@ describe('relations', function () {
|
||||||
var Other;
|
var Other;
|
||||||
|
|
||||||
before(function () {
|
before(function () {
|
||||||
tmp = getSchema('transient');
|
tmp = getTransientDataSource();
|
||||||
db = getSchema();
|
db = getSchema();
|
||||||
Person = db.define('Person', {name: String});
|
Person = db.define('Person', {name: String});
|
||||||
Passport = tmp.define('Passport',
|
Passport = tmp.define('Passport',
|
||||||
|
@ -1828,7 +1834,7 @@ describe('relations', function () {
|
||||||
var address1, address2;
|
var address1, address2;
|
||||||
|
|
||||||
before(function (done) {
|
before(function (done) {
|
||||||
tmp = getSchema('transient', {defaultIdType: Number});
|
tmp = getTransientDataSource({defaultIdType: Number});
|
||||||
db = getSchema();
|
db = getSchema();
|
||||||
Person = db.define('Person', {name: String});
|
Person = db.define('Person', {name: String});
|
||||||
Address = tmp.define('Address', {street: String});
|
Address = tmp.define('Address', {street: String});
|
||||||
|
@ -2008,7 +2014,7 @@ describe('relations', function () {
|
||||||
|
|
||||||
describe('embedsMany - explicit ids', function () {
|
describe('embedsMany - explicit ids', function () {
|
||||||
before(function (done) {
|
before(function (done) {
|
||||||
tmp = getSchema('transient');
|
tmp = getTransientDataSource();
|
||||||
db = getSchema();
|
db = getSchema();
|
||||||
Person = db.define('Person', {name: String});
|
Person = db.define('Person', {name: String});
|
||||||
Address = tmp.define('Address', {street: String});
|
Address = tmp.define('Address', {street: String});
|
||||||
|
@ -2415,11 +2421,16 @@ describe('relations', function () {
|
||||||
|
|
||||||
before(function (done) {
|
before(function (done) {
|
||||||
db = getSchema();
|
db = getSchema();
|
||||||
|
tmp = getTransientDataSource();
|
||||||
|
|
||||||
Book = db.define('Book', {name: String});
|
Book = db.define('Book', {name: String});
|
||||||
Author = db.define('Author', {name: String});
|
Author = db.define('Author', {name: String});
|
||||||
Reader = db.define('Reader', {name: String});
|
Reader = db.define('Reader', {name: String});
|
||||||
|
|
||||||
Link = db.define('Link', {name: String, notes: String}); // generic model
|
Link = tmp.define('Link', {
|
||||||
|
id: {type: Number, id: true},
|
||||||
|
name: String, notes: String
|
||||||
|
}); // generic model
|
||||||
Link.validatesPresenceOf('linkedId');
|
Link.validatesPresenceOf('linkedId');
|
||||||
Link.validatesPresenceOf('linkedType');
|
Link.validatesPresenceOf('linkedType');
|
||||||
|
|
||||||
|
@ -2433,13 +2444,15 @@ describe('relations', function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can be declared', function (done) {
|
it('can be declared', function (done) {
|
||||||
|
var idType = db.connector.getDefaultIdType();
|
||||||
|
|
||||||
Book.embedsMany(Link, { as: 'people',
|
Book.embedsMany(Link, { as: 'people',
|
||||||
polymorphic: 'linked',
|
polymorphic: 'linked',
|
||||||
scope: { include: 'linked' }
|
scope: { include: 'linked' }
|
||||||
});
|
});
|
||||||
Link.belongsTo('linked', {
|
Link.belongsTo('linked', {
|
||||||
polymorphic: true, // needs unique auto-id
|
polymorphic: { idType: idType }, // native type
|
||||||
properties: { name: 'name' }, // denormalized
|
properties: { name: 'name' }, // denormalized
|
||||||
options: { invertProperties: true }
|
options: { invertProperties: true }
|
||||||
});
|
});
|
||||||
db.automigrate(done);
|
db.automigrate(done);
|
||||||
|
|
|
@ -6,10 +6,14 @@ var should = require('./init.js');
|
||||||
|
|
||||||
var db, TransientModel, Person, Widget, Item;
|
var db, TransientModel, Person, Widget, Item;
|
||||||
|
|
||||||
|
var getTransientDataSource = function(settings) {
|
||||||
|
return new DataSource('transient', settings);
|
||||||
|
};
|
||||||
|
|
||||||
describe('Transient connector', function () {
|
describe('Transient connector', function () {
|
||||||
|
|
||||||
before(function () {
|
before(function () {
|
||||||
db = getSchema('transient');
|
db = getTransientDataSource();
|
||||||
TransientModel = db.define('TransientModel', {}, { idInjection: false });
|
TransientModel = db.define('TransientModel', {}, { idInjection: false });
|
||||||
|
|
||||||
Person = TransientModel.extend('Person', {name: String});
|
Person = TransientModel.extend('Person', {name: String});
|
||||||
|
|
Loading…
Reference in New Issue