Updated embedded relations to use transient connector

embedsMany will now use a connector's generated method, when defined.
Also, the id property type is now inferred correctly, making the autoId
option obsolete. However, a new option, forceId, can be set to enforce
the use of auto-generated ids, preventing any explicitly (user-)set id
values.
This commit is contained in:
Fabien Franzen 2014-08-30 11:43:36 +02:00
parent bd9895ebd6
commit f31a9b13be
4 changed files with 75 additions and 51 deletions

View File

@ -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);
};

View File

@ -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);
});

View File

@ -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 () {

View File

@ -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) {