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

Commit e710a423 by Luc Verdier Committed by Jan Aagaard Meier

Add context and custom options to nested creation (#5790)

1 parent c3179058
# Future # Future
- [FIXED] Method QueryInterface.bulkDelete no longer working when the model parameter is missing. (PostgreSQL) [#5615](https://github.com/sequelize/sequelize/issues/5615) - [FIXED] Method QueryInterface.bulkDelete no longer working when the model parameter is missing. (PostgreSQL) [#5615](https://github.com/sequelize/sequelize/issues/5615)
- [ADDED] Context and custom options for deep creation
# 3.22.0 # 3.22.0
- [FIXED] Fix defaultValues getting overwritten on build - [FIXED] Fix defaultValues getting overwritten on build
......
...@@ -634,10 +634,15 @@ Instance.prototype.save = function(options) { ...@@ -634,10 +634,15 @@ Instance.prototype.save = function(options) {
var instance = self.get(include.as); var instance = self.get(include.as);
if (!instance) return Promise.resolve(); if (!instance) return Promise.resolve();
return instance.save({ var includeOptions = _(self.$Model.$optClone(include))
transaction: options.transaction, .omit(['association'])
logging: options.logging .defaults({
}).then(function () { transaction: options.transaction,
logging: options.logging,
parentRecord: self
}).value();
return instance.save(includeOptions).then(function () {
return self[include.association.accessors.set](instance, {save: false, logging: options.logging}); return self[include.association.accessors.set](instance, {save: false, logging: options.logging});
}); });
}); });
...@@ -707,18 +712,26 @@ Instance.prototype.save = function(options) { ...@@ -707,18 +712,26 @@ Instance.prototype.save = function(options) {
if (!Array.isArray(instances)) instances = [instances]; if (!Array.isArray(instances)) instances = [instances];
if (!instances.length) return Promise.resolve(); if (!instances.length) return Promise.resolve();
var includeOptions = _(self.$Model.$optClone(include))
.omit(['association'])
.defaults({
transaction: options.transaction,
logging: options.logging,
parentRecord: self
}).value();
// Instances will be updated in place so we can safely treat HasOne like a HasMany // Instances will be updated in place so we can safely treat HasOne like a HasMany
return Promise.map(instances, function (instance) { return Promise.map(instances, function (instance) {
if (include.association instanceof BelongsToMany) { if (include.association instanceof BelongsToMany) {
return instance.save({transaction: options.transaction, logging: options.logging}).then(function () { return instance.save(includeOptions).then(function () {
var values = {}; var values = {};
values[include.association.foreignKey] = self.get(self.Model.primaryKeyAttribute, {raw: true}); values[include.association.foreignKey] = self.get(self.Model.primaryKeyAttribute, {raw: true});
values[include.association.otherKey] = instance.get(instance.Model.primaryKeyAttribute, {raw: true}); values[include.association.otherKey] = instance.get(instance.Model.primaryKeyAttribute, {raw: true});
return include.association.throughModel.create(values, {transaction: options.transaction, logging: options.logging}); return include.association.throughModel.create(values, includeOptions);
}); });
} else { } else {
instance.set(include.association.foreignKey, self.get(self.Model.primaryKeyAttribute, {raw: true})); instance.set(include.association.foreignKey, self.get(self.Model.primaryKeyAttribute, {raw: true}));
return instance.save({transaction: options.transaction, logging: options.logging}); return instance.save(includeOptions);
} }
}); });
}); });
......
...@@ -17,6 +17,12 @@ describe(Support.getTestDialectTeaser('Model'), function() { ...@@ -17,6 +17,12 @@ describe(Support.getTestDialectTeaser('Model'), function() {
var User = this.sequelize.define('User', { var User = this.sequelize.define('User', {
first_name: Sequelize.STRING, first_name: Sequelize.STRING,
last_name: Sequelize.STRING last_name: Sequelize.STRING
}, {
hooks: {
beforeCreate: function (user, options) {
user.createOptions = options;
}
}
}); });
Product.belongsTo(User); Product.belongsTo(User);
...@@ -29,8 +35,13 @@ describe(Support.getTestDialectTeaser('Model'), function() { ...@@ -29,8 +35,13 @@ describe(Support.getTestDialectTeaser('Model'), function() {
last_name: 'Broadstone' last_name: 'Broadstone'
} }
}, { }, {
include: [ User ] include: [{
model: User,
myOption: 'option'
}]
}).then(function(savedProduct) { }).then(function(savedProduct) {
expect(savedProduct.User.createOptions.myOption).to.be.equal('option');
expect(savedProduct.User.createOptions.parentRecord).to.be.equal(savedProduct);
return Product.findOne({ return Product.findOne({
where: { id: savedProduct.id }, where: { id: savedProduct.id },
include: [ User ] include: [ User ]
...@@ -82,6 +93,12 @@ describe(Support.getTestDialectTeaser('Model'), function() { ...@@ -82,6 +93,12 @@ describe(Support.getTestDialectTeaser('Model'), function() {
}); });
var Tag = this.sequelize.define('Tag', { var Tag = this.sequelize.define('Tag', {
name: Sequelize.STRING name: Sequelize.STRING
}, {
hooks: {
afterCreate: function (tag, options) {
tag.createOptions = options;
}
}
}); });
Product.hasMany(Tag); Product.hasMany(Tag);
...@@ -95,7 +112,10 @@ describe(Support.getTestDialectTeaser('Model'), function() { ...@@ -95,7 +112,10 @@ describe(Support.getTestDialectTeaser('Model'), function() {
{id: 2, name: 'Beta'} {id: 2, name: 'Beta'}
] ]
}, { }, {
include: [ Tag ] include: [{
model: Tag,
myOption: 'option'
}]
}).then(function(savedProduct) { }).then(function(savedProduct) {
return Product.find({ return Product.find({
where: { id: savedProduct.id }, where: { id: savedProduct.id },
...@@ -209,6 +229,12 @@ describe(Support.getTestDialectTeaser('Model'), function() { ...@@ -209,6 +229,12 @@ describe(Support.getTestDialectTeaser('Model'), function() {
var Task = this.sequelize.define('Task', { var Task = this.sequelize.define('Task', {
title: DataTypes.STRING, title: DataTypes.STRING,
active: DataTypes.BOOLEAN active: DataTypes.BOOLEAN
}, {
hooks: {
afterCreate: function (task, options) {
task.createOptions = options;
}
}
}); });
User.belongsToMany(Task, {through: 'user_task'}); User.belongsToMany(Task, {through: 'user_task'});
...@@ -222,8 +248,15 @@ describe(Support.getTestDialectTeaser('Model'), function() { ...@@ -222,8 +248,15 @@ describe(Support.getTestDialectTeaser('Model'), function() {
{ title: 'Die trying', active: false } { title: 'Die trying', active: false }
] ]
}, { }, {
include: [ Task ] include: [{
model: Task,
myOption: 'option'
}]
}).then(function(savedUser) { }).then(function(savedUser) {
expect(savedUser.Tasks[0].createOptions.myOption).to.be.equal('option');
expect(savedUser.Tasks[0].createOptions.parentRecord).to.be.equal(savedUser);
expect(savedUser.Tasks[1].createOptions.myOption).to.be.equal('option');
expect(savedUser.Tasks[1].createOptions.parentRecord).to.be.equal(savedUser);
return User.find({ return User.find({
where: { id: savedUser.id }, where: { id: savedUser.id },
include: [ Task ] include: [ Task ]
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!