support embeds data for belongsTo relation

Signed-off-by: Clark Wang <clark.wangs@gmail.com>
This commit is contained in:
Clark Wang 2015-01-19 22:49:20 +08:00
parent 0019501a8b
commit 83c3a17f87
3 changed files with 60 additions and 1 deletions

View File

@ -13,6 +13,8 @@ var List = require('./list');
var Hookable = require('./hooks'); var Hookable = require('./hooks');
var validations = require('./validations'); var validations = require('./validations');
var _extend = util._extend; var _extend = util._extend;
var utils = require('./utils');
var fieldsToArray = utils.fieldsToArray;
// Set up an object for quick lookup // Set up an object for quick lookup
var BASE_TYPES = { var BASE_TYPES = {
@ -170,7 +172,16 @@ ModelBaseClass.prototype._initProperties = function (data, options) {
if (relationType === 'belongsTo' && propVal != null) { if (relationType === 'belongsTo' && propVal != null) {
// If the related model is populated // If the related model is populated
self.__data[ctor.relations[p].keyFrom] = propVal[ctor.relations[p].keyTo]; self.__data[ctor.relations[p].keyFrom] = propVal[ctor.relations[p].keyTo];
if (ctor.relations[p].options.embedsProperties) {
var fields = fieldsToArray(ctor.relations[p].properties, modelTo.definition.properties);
if (!~fields.indexOf(ctor.relations[p].keyTo)) {
fields.push(ctor.relations[p].keyTo);
}
self.__data[p] = new modelTo(propVal, { fields: fields, applySetters: false, persisted: options.persisted });
}
} }
self.__cachedRelations[p] = propVal; self.__cachedRelations[p] = propVal;
} else { } else {
// Un-managed property // Un-managed property

View File

@ -208,11 +208,20 @@ RelationDefinition.prototype.applyProperties = function(modelInstance, obj) {
if (this.options.invertProperties) { if (this.options.invertProperties) {
source = obj, target = modelInstance; source = obj, target = modelInstance;
} }
if (this.options.embedsProperties) {
target = target.__data[this.name] = {};
target[this.keyTo] = source[this.keyTo];
}
if (typeof this.properties === 'function') { if (typeof this.properties === 'function') {
var data = this.properties.call(this, source); var data = this.properties.call(this, source);
for(var k in data) { for(var k in data) {
target[k] = data[k]; target[k] = data[k];
} }
} else if (Array.isArray(this.properties)) {
for(var k = 0; k < this.properties.length; k++) {
var key = this.properties[k];
target[key] = source[key];
}
} else if (typeof this.properties === 'object') { } else if (typeof this.properties === 'object') {
for(var k in this.properties) { for(var k in this.properties) {
var key = this.properties[k]; var key = this.properties[k];
@ -1309,7 +1318,7 @@ BelongsTo.prototype.related = function (refresh, params) {
} }
var cb = params; var cb = params;
if (cachedValue === undefined) { if (cachedValue === undefined || !(cachedValue instanceof ModelBaseClass)) {
var query = {where: {}}; var query = {where: {}};
query.where[pk] = modelInstance[fk]; query.where[pk] = modelInstance[fk];

View File

@ -1718,6 +1718,45 @@ describe('relations', function () {
}); });
describe('belongsTo with embed', function () {
var Person, Passport;
it('can be declared with embed and properties', function (done) {
Person = db.define('Person', {name: String, age: Number});
Passport = db.define('Passport', {name: String, notes: String});
Passport.belongsTo(Person, {
properties: ['name'],
options: { embedsProperties: true, invertProperties: true }
});
db.automigrate(done);
});
it('should create record with embedded data', function (done) {
Person.create({name: 'Fred', age: 36 }, function(err, person) {
var p = new Passport({ name: 'Passport', notes: 'Some notes...' });
p.person(person);
p.personId.should.equal(person.id);
var data = p.toObject(true);
data.person.id.should.equal(person.id);
data.person.name.should.equal('Fred');
p.save(function (err) {
should.not.exists(err);
done();
});
});
});
it('should find record with embedded data', function (done) {
Passport.findOne(function (err, p) {
should.not.exists(err);
var data = p.toObject(true);
data.person.id.should.equal(p.personId);
data.person.name.should.equal('Fred');
done();
});
});
});
describe('hasOne', function () { describe('hasOne', function () {
var Supplier, Account; var Supplier, Account;
var supplierId, accountId; var supplierId, accountId;