diff --git a/lib/relation-definition.js b/lib/relation-definition.js index 3185a6a4..3a5b7371 100644 --- a/lib/relation-definition.js +++ b/lib/relation-definition.js @@ -391,13 +391,13 @@ util.inherits(HasOne, Relation); * EmbedsOne subclass * @param {RelationDefinition|Object} definition * @param {Object} modelInstance - * @returns {EmbedsMany} + * @returns {EmbedsOne} * @constructor * @class EmbedsOne */ function EmbedsOne(definition, modelInstance) { if (!(this instanceof EmbedsOne)) { - return new EmbedsMany(definition, modelInstance); + return new EmbedsOne(definition, modelInstance); } assert(definition.type === RelationTypes.embedsOne); 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 * @returns {Object} The normalized parameters */ -function polymorphicParams(params) { +function polymorphicParams(params, as) { 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.discriminator = params.discriminator || i8n.camelize(params.as + '_type', true); return params; @@ -1079,21 +1079,23 @@ RelationDefinition.belongsTo = function (modelFrom, modelTo, params) { var idName, relationName, fk; if (params.polymorphic) { + relationName = params.as || (typeof modelTo === 'string' ? modelTo : null); // initially + if (params.polymorphic === true) { // modelTo arg will be the name of the polymorphic relation (string) - polymorphic = polymorphicParams(modelTo); + polymorphic = polymorphicParams(modelTo, relationName); } else { - polymorphic = polymorphicParams(params.polymorphic); + polymorphic = polymorphicParams(params.polymorphic, relationName); } modelTo = null; // will lookup dynamically idName = params.idName || 'id'; - relationName = params.as || polymorphic.as; + relationName = params.as || polymorphic.as; // finally fk = polymorphic.foreignKey; 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 }); } else { // try to use the same foreign key type as modelFrom modelFrom.dataSource.defineForeignKey(modelFrom.modelName, fk, modelFrom.modelName); @@ -2208,10 +2210,7 @@ EmbedsMany.prototype.build = function(targetModelData) { var assignId = (forceId || targetModelData[pk] === undefined); - if (assignId && typeof connector.generateId === 'function') { - var id = connector.generateId(modelTo.modelName, targetModelData, pk); - targetModelData[pk] = id; - } else if (assignId && pkType === Number) { + if (assignId && pkType === Number) { var ids = embeddedList.map(function(m) { return (typeof m[pk] === 'number' ? m[pk] : 0); }); @@ -2220,6 +2219,9 @@ EmbedsMany.prototype.build = function(targetModelData) { } else { 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); diff --git a/test/relations.test.js b/test/relations.test.js index 89607fc7..b99f31ba 100644 --- a/test/relations.test.js +++ b/test/relations.test.js @@ -1,5 +1,7 @@ // This test written in mocha+should.js var should = require('./init.js'); +var jdb = require('../'); +var DataSource = jdb.DataSource; var db, tmp, Book, Chapter, Author, Reader; var Category, Job; @@ -7,6 +9,10 @@ var Picture, PictureLink; var Person, Address; var Link; +var getTransientDataSource = function(settings) { + return new DataSource('transient', settings, db.modelBuilder); +}; + describe('relations', function () { describe('hasMany', function () { @@ -1679,7 +1685,7 @@ describe('relations', function () { var Other; before(function () { - tmp = getSchema('transient'); + tmp = getTransientDataSource(); db = getSchema(); Person = db.define('Person', {name: String}); Passport = tmp.define('Passport', @@ -1828,7 +1834,7 @@ describe('relations', function () { var address1, address2; before(function (done) { - tmp = getSchema('transient', {defaultIdType: Number}); + tmp = getTransientDataSource({defaultIdType: Number}); db = getSchema(); Person = db.define('Person', {name: String}); Address = tmp.define('Address', {street: String}); @@ -2008,7 +2014,7 @@ describe('relations', function () { describe('embedsMany - explicit ids', function () { before(function (done) { - tmp = getSchema('transient'); + tmp = getTransientDataSource(); db = getSchema(); Person = db.define('Person', {name: String}); Address = tmp.define('Address', {street: String}); @@ -2415,11 +2421,16 @@ describe('relations', function () { before(function (done) { db = getSchema(); + tmp = getTransientDataSource(); + Book = db.define('Book', {name: String}); Author = db.define('Author', {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('linkedType'); @@ -2433,13 +2444,15 @@ describe('relations', function () { }); it('can be declared', function (done) { + var idType = db.connector.getDefaultIdType(); + Book.embedsMany(Link, { as: 'people', polymorphic: 'linked', scope: { include: 'linked' } }); Link.belongsTo('linked', { - polymorphic: true, // needs unique auto-id - properties: { name: 'name' }, // denormalized + polymorphic: { idType: idType }, // native type + properties: { name: 'name' }, // denormalized options: { invertProperties: true } }); db.automigrate(done); diff --git a/test/transient.test.js b/test/transient.test.js index ec713a9c..e3a03f96 100644 --- a/test/transient.test.js +++ b/test/transient.test.js @@ -6,10 +6,14 @@ var should = require('./init.js'); var db, TransientModel, Person, Widget, Item; +var getTransientDataSource = function(settings) { + return new DataSource('transient', settings); +}; + describe('Transient connector', function () { before(function () { - db = getSchema('transient'); + db = getTransientDataSource(); TransientModel = db.define('TransientModel', {}, { idInjection: false }); Person = TransientModel.extend('Person', {name: String});