不要怂,就是干,撸起袖子干!

Commit bc359e40 by Matt Broadstone

initial support for relations in Instance.save

This allows users to insert association data into the databased by
specifying the proper include models in their build() data.
1 parent dabefbe8
......@@ -572,6 +572,36 @@ module.exports = (function() {
}).then(function() {
if (!options.fields.length) return this;
// create relational data for BelongsTo
var relationPromises = [];
Object.keys(this.dataValues).forEach(function(dataValue) {
if (_.has(self.options.includeMap, dataValue)) {
var includeModel = self.options.includeMap[dataValue].model;
var includeAssociation = self.options.includeMap[dataValue].association;
if (includeAssociation.associationType === 'BelongsTo') {
var includeData = self.dataValues[dataValue].dataValues;
var relationPromise = includeModel.create(includeData).then(function(result) {
result._originalDataValue = dataValue;
result._identifierField = includeAssociation.identifierField;
return result;
});
relationPromises.push(relationPromise);
}
}
});
return Promise.all(relationPromises).then(function(instances) {
instances.forEach(function(instance) {
delete self.dataValues[instance._originalDataValue];
self.dataValues[instance._identifierField] = instance.id;
});
});
})
.then(function() {
if (!options.fields.length) return this;
var values = Utils.mapValueFieldNames(this.dataValues, options.fields, this.Model)
, query = null
, args = [];
......@@ -630,6 +660,46 @@ module.exports = (function() {
});
self.isNewRecord = false;
return result;
})
.tap(function(result) {
// handle HasOne/HasMany/BelongsToMany relations
var relationPromises = [];
Object.keys(self.dataValues).forEach(function(dataValue) {
if (_.has(self.options.includeMap, dataValue)) {
var includeModel = self.options.includeMap[dataValue].model;
var includeAssociation = self.options.includeMap[dataValue].association;
if (includeAssociation.associationType === 'HasOne') {
var includeData = self.dataValues[dataValue].dataValues;
includeData[includeAssociation.identifierField] = result.id;
relationPromises.push(includeModel.create(includeData));
} else if (includeAssociation.associationType === 'HasMany') {
self.dataValues[dataValue].forEach(function(record) {
var includeData = record.dataValues;
includeData[includeAssociation.identifierField] = result.id;
relationPromises.push(includeModel.create(includeData));
});
} else if (includeAssociation.associationType === 'BelongsToMany') {
var throughModel = includeAssociation.throughModel;
var identifierField = includeAssociation.identifierField;
var foreignIdentifierField = includeAssociation.foreignIdentifierField;
self.dataValues[dataValue].forEach(function(record) {
var includeData = record.dataValues;
var promise = includeModel.create(includeData).then(function(associatedRecord) {
var throughData = {};
throughData[identifierField] = result.id;
throughData[foreignIdentifierField] = associatedRecord.id;
return throughModel.create(throughData);
});
relationPromises.push(promise);
});
}
}
});
return Promise.all(relationPromises);
});
});
});
......
......@@ -1321,8 +1321,6 @@ describe(Support.getTestDialectTeaser('Instance'), function() {
user.age = user.age + 1; // happy birthday joe
user.save().done(function(err) {
expect(err).not.to.be.ok;
expect(user.username).to.equal('joe');
expect(user.age).to.equal(2);
expect(user.Projects).to.exist;
......
'use strict';
var chai = require('chai')
, Sequelize = require('../../../index')
, expect = chai.expect
, Support = require(__dirname + '/../support')
, dialect = Support.getTestDialect()
, DataTypes = require(__dirname + '/../../../lib/data-types')
, Promise = Sequelize.Promise;
chai.config.includeStack = true;
describe(Support.getTestDialectTeaser('Instance'), function() {
describe('save', function() {
describe('include', function() {
it('should save data for BelongsTo relations', function() {
var Product = this.sequelize.define('Product', {
title: Sequelize.STRING
});
var User = this.sequelize.define('User', {
first_name: Sequelize.STRING,
last_name: Sequelize.STRING
});
Product.belongsTo(User);
var product = Product.build({
id: 1,
title: 'Chair',
User: {
id: 1,
first_name: 'Mick',
last_name: 'Hansen'
}
}, {
include: [ User ]
});
return this.sequelize.sync({ force: true }).then(function() {
return product.save().then(function(savedProduct) {
return Product.find({
where: { id: savedProduct.id },
include: [ User ]
}).then(function(persistedProduct) {
expect(persistedProduct.User).to.be.ok;
});
});
});
});
it('should save data for HasMany relations', function() {
var Product = this.sequelize.define('Product', {
title: Sequelize.STRING
});
var Tag = this.sequelize.define('Tag', {
name: Sequelize.STRING
});
Product.hasMany(Tag);
var product = Product.build({
id: 1,
title: 'Chair',
Tags: [
{id: 1, name: 'Alpha'},
{id: 2, name: 'Beta'}
]
}, {
include: [ Tag ]
});
return this.sequelize.sync({ force: true }).then(function() {
return product.save().then(function(savedProduct) {
return Product.find({
where: { id: savedProduct.id },
include: [ Tag ]
}).then(function(persistedProduct) {
expect(persistedProduct.Tags).to.be.ok;
expect(persistedProduct.Tags.length).to.equal(2);
});
});
});
});
it('should save data for HasOne relations', function() {
var User = this.sequelize.define('User', {
username: Sequelize.STRING
});
var Task = this.sequelize.define('Task', {
title: Sequelize.STRING
});
User.hasOne(Task);
var user = User.build({
username: 'Muzzy',
Task: {
title: 'Eat Clocks'
}
}, {
include: [ Task ]
});
return this.sequelize.sync({ force: true }).then(function() {
return user.save().then(function(savedUser) {
return User.find({
where: { id: savedUser.id },
include: [ Task ]
}).then(function(persistedUser) {
expect(persistedUser.Task).to.be.ok;
});
});
});
});
it('should save data for BelongsToMany relations', function() {
var User = this.sequelize.define('User', {
username: DataTypes.STRING
});
var Task = this.sequelize.define('Task', {
title: DataTypes.STRING,
active: DataTypes.BOOLEAN
});
User.belongsToMany(Task);
Task.belongsToMany(User);
var user = User.build({
username: 'John',
Tasks: [
{ title: 'Get rich', active: true },
{ title: 'Die trying', active: false }
]
}, {
include: [ Task ]
});
var tasks = [];
return this.sequelize.sync({ force: true }).then(function() {
return user.save().then(function(savedUser) {
return User.find({
where: { id: savedUser.id },
include: [ Task ]
}).then(function(persistedUser) {
expect(persistedUser.Tasks).to.be.ok;
expect(persistedUser.Tasks.length).to.equal(2);
});
});
});
});
});
});
});
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!