diff --git a/lib/connectors/transient.js b/lib/connectors/transient.js index 97e693e3..ce8354ce 100644 --- a/lib/connectors/transient.js +++ b/lib/connectors/transient.js @@ -50,9 +50,12 @@ Transient.prototype.connect = function (callback) { } }; -Transient.prototype.generateId = function(model, data, idType) { +Transient.prototype.generateId = function(model, data, idName) { + var idType; + var props = this._models[model].properties; + if (idName) idType = props[idName] && props[idName].type; idType = idType || this.getDefaultIdType(); - if (idType === Number || idType === 'number') { + if (idType === Number) { return Math.floor(Math.random() * 10000); // max. 4 digits } else { return crypto.randomBytes(Math.ceil(24/2)) @@ -61,30 +64,6 @@ Transient.prototype.generateId = function(model, data, idType) { } }; -/*! - * Flush the cache - noop. - * @param {Function} callback - */ -Transient.prototype.flush = function (result, callback) { - process.nextTick(function () { callback && callback(null, result); }); -}; - -Transient.prototype.create = function create(model, data, callback) { - var idName = this.idName(model); - if (idName) { - var props = this._models[model].properties; - var idType = props[idName] && props[idName].type; - var id = this.getIdValue(model, data) || this.generateId(model, data, idType); - id = (props[idName] && props[idName].type && props[idName].type(id)) || id; - this.setIdValue(model, data, id); - } - this.flush(id, callback); -}; - -Transient.prototype.save = function save(model, data, callback) { - this.flush(data, callback); -}; - Transient.prototype.exists = function exists(model, id, callback) { process.nextTick(function () { callback(null, false); }.bind(this)); }; @@ -93,29 +72,32 @@ Transient.prototype.find = function find(model, id, callback) { process.nextTick(function () { callback(null, null); }.bind(this)); }; -Transient.prototype.destroy = function destroy(model, id, callback) { - this.flush(null, callback); -}; - Transient.prototype.all = function all(model, filter, callback) { process.nextTick(function () { callback(null, []); }); }; -Transient.prototype.destroyAll = function destroyAll(model, where, callback) { - if (!callback && 'function' === typeof where) { - callback = where; - where = undefined; - } - this.flush(null, callback); -}; - Transient.prototype.count = function count(model, callback, where) { process.nextTick(function () { callback(null, 0); }); }; +Transient.prototype.create = function create(model, data, callback) { + var props = this._models[model].properties; + var idName = this.idName(model); + if (idName && props[idName]) { + var id = this.getIdValue(model, data) || this.generateId(model, data, idName); + id = (props[idName] && props[idName].type && props[idName].type(id)) || id; + this.setIdValue(model, data, id); + } + this.flush('create', id, callback); +}; + +Transient.prototype.save = function save(model, data, callback) { + this.flush('save', data, callback); +}; + Transient.prototype.update = Transient.prototype.updateAll = function updateAll(model, where, data, cb) { - this.flush(null, cb); + this.flush('update', null, cb); }; Transient.prototype.updateAttributes = function updateAttributes(model, id, data, cb) { @@ -132,6 +114,26 @@ Transient.prototype.updateAttributes = function updateAttributes(model, id, data this.save(model, data, cb); }; +Transient.prototype.destroy = function destroy(model, id, callback) { + this.flush('destroy', null, callback); +}; + +Transient.prototype.destroyAll = function destroyAll(model, where, callback) { + if (!callback && 'function' === typeof where) { + callback = where; + where = undefined; + } + this.flush('destroyAll', null, callback); +}; + +/*! + * Flush the cache - noop. + * @param {Function} callback + */ +Transient.prototype.flush = function (action, result, callback) { + process.nextTick(function () { callback && callback(null, result); }); +}; + Transient.prototype.transaction = function () { return new Transient(this); }; diff --git a/lib/relation-definition.js b/lib/relation-definition.js index 540d0dd1..0a318988 100644 --- a/lib/relation-definition.js +++ b/lib/relation-definition.js @@ -1842,8 +1842,9 @@ RelationDefinition.embedsMany = function embedsMany(modelFrom, modelTo, params) type: [modelTo], default: function() { return []; } }); - // unique id is required - modelTo.validatesPresenceOf(idName); + if (typeof modelTo.dataSource.connector.generateId !== 'function') { + modelTo.validatesPresenceOf(idName); // unique id is required + } if (!params.polymorphic) { modelFrom.validate(propertyName, function(err) { @@ -2143,7 +2144,6 @@ EmbedsMany.prototype.create = function (targetModelData, cb) { var modelTo = this.definition.modelTo; var propertyName = this.definition.keyFrom; var modelInstance = this.modelInstance; - var autoId = this.definition.options.autoId !== false; if (typeof targetModelData === 'function' && !cb) { cb = targetModelData; @@ -2170,16 +2170,25 @@ EmbedsMany.prototype.create = function (targetModelData, cb) { }; EmbedsMany.prototype.build = function(targetModelData) { - var pk = this.definition.keyTo; var modelTo = this.definition.modelTo; var modelInstance = this.modelInstance; - var autoId = this.definition.options.autoId !== false; + var forceId = this.definition.options.forceId; + var connector = modelTo.dataSource.connector; + + var pk = this.definition.keyTo; + var pkProp = modelTo.definition.properties[pk] + var pkType = pkProp && pkProp.type; var embeddedList = this.embeddedList(); targetModelData = targetModelData || {}; - if (typeof targetModelData[pk] !== 'number' && autoId) { + 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) { var ids = embeddedList.map(function(m) { return (typeof m[pk] === 'number' ? m[pk] : 0); }); diff --git a/test/relations.test.js b/test/relations.test.js index 4765f45d..469db883 100644 --- a/test/relations.test.js +++ b/test/relations.test.js @@ -1486,9 +1486,10 @@ describe('relations', function () { var Other; before(function () { + tmp = getSchema('transient'); db = getSchema(); Person = db.define('Person', {name: String}); - Passport = db.define('Passport', + Passport = tmp.define('Passport', {name:{type:'string', required: true}}, {idInjection: false} ); @@ -1634,9 +1635,10 @@ describe('relations', function () { var address1, address2; before(function (done) { + tmp = getSchema('transient', {defaultIdType: Number}); db = getSchema(); Person = db.define('Person', {name: String}); - Address = db.define('Address', {street: String}); + Address = tmp.define('Address', {street: String}); Address.validatesPresenceOf('street'); db.automigrate(function () { @@ -1813,9 +1815,10 @@ describe('relations', function () { describe('embedsMany - explicit ids', function () { before(function (done) { + tmp = getSchema('transient'); db = getSchema(); Person = db.define('Person', {name: String}); - Address = db.define('Address', {id: { type: String, id: true }, street: String}); + Address = tmp.define('Address', {street: String}); Address.validatesPresenceOf('street'); db.automigrate(function () { @@ -1824,13 +1827,13 @@ describe('relations', function () { }); it('can be declared', function (done) { - Person.embedsMany(Address, { options: { autoId: false } }); + Person.embedsMany(Address); db.automigrate(done); }); it('should create embedded items on scope', function(done) { Person.create({ name: 'Fred' }, function(err, p) { - p.addressList.create({ id: 'home', street: 'Street 1' }, function(err, addresses) { + p.addressList.create({ id: 'home', street: 'Street 1' }, function(err, address) { should.not.exist(err); p.addressList.create({ id: 'work', street: 'Work Street 2' }, function(err, address) { should.not.exist(err); @@ -1968,6 +1971,17 @@ describe('relations', function () { }); }); + it('should create embedded items with auto-generated id', function(done) { + Person.create({ name: 'Wilma' }, function(err, p) { + p.addressList.create({ street: 'Home Street 1' }, function(err, address) { + should.not.exist(err); + address.id.should.match(/^[0-9a-fA-F]{24}$/); + address.street.should.equal('Home Street 1'); + done(); + }); + }); + }); + }); describe('embedsMany - relations, scope and properties', function () { diff --git a/test/transient.test.js b/test/transient.test.js index 61d847d2..ec713a9c 100644 --- a/test/transient.test.js +++ b/test/transient.test.js @@ -64,7 +64,6 @@ describe('Transient connector', function () { Item.create({ name: 'Example' }, function(err, inst) { should.not.exist(err); - inst.id.should.be.a.number; inst.name.should.equal('Example'); Item.count(function(err, count) {