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

Commit 010db1d9 by Simon Schick

refactor: replace _.defaults with spread

1 parent 8e4f4a94
......@@ -246,8 +246,11 @@ class BelongsToMany extends Association {
const targetKey = this.target.rawAttributes[this.target.primaryKeyAttribute];
const targetKeyType = targetKey.type;
const targetKeyField = targetKey.field || this.target.primaryKeyAttribute;
const sourceAttribute = _.defaults({}, this.foreignKeyAttribute, { type: sourceKeyType });
const targetAttribute = _.defaults({}, this.otherKeyAttribute, { type: targetKeyType });
const sourceAttribute = {
type: sourceKeyType,
...this.foreignKeyAttribute
};
const targetAttribute = { type: targetKeyType, ...this.otherKeyAttribute };
if (this.primaryKeyDeleted === true) {
targetAttribute.primaryKey = sourceAttribute.primaryKey = true;
......@@ -550,7 +553,7 @@ class BelongsToMany extends Association {
throughAttributes = {};
}
const attributes = _.defaults({}, throughAttributes, defaultAttributes);
const attributes = { ...defaultAttributes, ...throughAttributes };
if (Object.keys(attributes).length) {
promises.push(
......@@ -572,25 +575,22 @@ class BelongsToMany extends Association {
[foreignIdentifier]: obsoleteAssociations.map(obsoleteAssociation => obsoleteAssociation[foreignIdentifier])
}, this.through.scope);
promises.push(
this.through.model.destroy(_.defaults({
this.through.model.destroy({
...options,
where
}, options))
})
);
}
if (unassociatedObjects.length > 0) {
const bulk = unassociatedObjects.map(unassociatedObject => {
let attributes = {};
attributes[identifier] = sourceInstance.get(sourceKey);
attributes[foreignIdentifier] = unassociatedObject.get(targetKey);
attributes = _.defaults(attributes, unassociatedObject[this.through.model.name], defaultAttributes);
Object.assign(attributes, this.through.scope);
attributes = Object.assign(attributes, this.through.scope);
return attributes;
return {
[identifier]: sourceInstance.get(sourceKey),
[foreignIdentifier]: unassociatedObject.get(targetKey),
...defaultAttributes,
...unassociatedObject[this.through.model.name],
...this.through.scope
};
});
promises.push(this.through.model.bulkCreate(bulk, Object.assign({ validate: true }, options)));
......@@ -599,7 +599,7 @@ class BelongsToMany extends Association {
return Utils.Promise.all(promises);
};
return this.through.model.findAll(_.defaults({ where, raw: true }, options))
return this.through.model.findAll({ ...options, where, raw: true })
.then(currentRows => updateAssociations(currentRows))
.catch(error => {
if (error instanceof EmptyResultError) return updateAssociations([]);
......@@ -652,7 +652,7 @@ class BelongsToMany extends Association {
unassociatedObjects.push(obj);
} else {
const throughAttributes = obj[association.through.model.name];
const attributes = _.defaults({}, throughAttributes, defaultAttributes);
const attributes = { ...defaultAttributes, ...throughAttributes };
if (Object.keys(attributes).some(attribute => attributes[attribute] !== existingAssociation[attribute])) {
changedAssociations.push(obj);
......@@ -663,39 +663,33 @@ class BelongsToMany extends Association {
if (unassociatedObjects.length > 0) {
const bulk = unassociatedObjects.map(unassociatedObject => {
const throughAttributes = unassociatedObject[association.through.model.name];
const attributes = _.defaults({}, throughAttributes, defaultAttributes);
attributes[identifier] = sourceInstance.get(sourceKey);
attributes[foreignIdentifier] = unassociatedObject.get(targetKey);
Object.assign(attributes, association.through.scope);
return attributes;
return {
...defaultAttributes,
...throughAttributes,
[identifier]: sourceInstance.get(sourceKey),
[foreignIdentifier]: unassociatedObject.get(targetKey),
...association.through.scope
};
});
promises.push(association.through.model.bulkCreate(bulk, Object.assign({ validate: true }, options)));
}
for (const assoc of changedAssociations) {
let throughAttributes = assoc[association.through.model.name];
const attributes = _.defaults({}, throughAttributes, defaultAttributes);
// Quick-fix for subtle bug when using existing objects that might have the through model attached (not as an attribute object)
if (throughAttributes instanceof association.through.model) {
throughAttributes = {};
}
const where = {
const attributes = { ...defaultAttributes, ...assoc[association.through.model.name] };
promises.push(association.through.model.update(attributes, Object.assign(options, {
where: {
[identifier]: sourceInstance.get(sourceKey),
[foreignIdentifier]: assoc.get(targetKey)
};
promises.push(association.through.model.update(attributes, Object.assign(options, { where })));
}
})));
}
return Utils.Promise.all(promises);
};
return association.through.model.findAll(_.defaults({ where, raw: true }, options))
return association.through.model.findAll({ ...options, where, raw: true })
.then(currentRows => updateAssociations(currentRows))
.then(([associations]) => associations)
.catch(error => {
......@@ -725,7 +719,7 @@ class BelongsToMany extends Association {
[association.foreignIdentifier]: oldAssociatedObjects.map(newInstance => newInstance.get(association.target.primaryKeyAttribute))
};
return association.through.model.destroy(_.defaults({ where }, options));
return association.through.model.destroy({ ...options, where });
}
/**
......
......@@ -79,12 +79,13 @@ class BelongsTo extends Association {
// the id is in the source table
_injectAttributes() {
const newAttributes = {};
newAttributes[this.foreignKey] = _.defaults({}, this.foreignKeyAttribute, {
const newAttributes = {
[this.foreignKey]: {
type: this.options.keyType || this.target.rawAttributes[this.targetKey].type,
allowNull: true
});
allowNull: true,
...this.foreignKeyAttribute
}
};
if (this.options.constraints !== false) {
const source = this.source.rawAttributes[this.foreignKey] || newAttributes[this.foreignKey];
......
......@@ -116,10 +116,11 @@ class HasMany extends Association {
// Create a new options object for use with addForeignKeyConstraints, to avoid polluting this.options in case it is later used for a n:m
const constraintOptions = { ...this.options };
newAttributes[this.foreignKey] = _.defaults({}, this.foreignKeyAttribute, {
newAttributes[this.foreignKey] = {
type: this.options.keyType || this.source.rawAttributes[this.sourceKeyAttribute].type,
allowNull: true
});
allowNull: true,
...this.foreignKeyAttribute
};
if (this.options.constraints !== false) {
const target = this.target.rawAttributes[this.foreignKey] || newAttributes[this.foreignKey];
......@@ -325,7 +326,11 @@ class HasMany extends Association {
targetInstances = this.toInstanceArray(targetInstances);
}
return this.get(sourceInstance, _.defaults({ scope: false, raw: true }, options)).then(oldAssociations => {
return this.get(sourceInstance, {
...options,
scope: false,
raw: true
}).then(oldAssociations => {
const promises = [];
const obsoleteAssociations = oldAssociations.filter(old =>
!targetInstances.find(obj =>
......@@ -353,9 +358,10 @@ class HasMany extends Association {
promises.push(this.target.unscoped().update(
update,
_.defaults({
{
...options,
where: updateWhere
}, options)
}
));
}
......@@ -372,9 +378,10 @@ class HasMany extends Association {
promises.push(this.target.unscoped().update(
update,
_.defaults({
{
...options,
where: updateWhere
}, options)
}
));
}
......@@ -408,7 +415,7 @@ class HasMany extends Association {
)
};
return this.target.unscoped().update(update, _.defaults({ where }, options)).return(sourceInstance);
return this.target.unscoped().update(update, { ...options, where }).return(sourceInstance);
}
/**
......@@ -434,7 +441,7 @@ class HasMany extends Association {
)
};
return this.target.unscoped().update(update, _.defaults({ where }, options)).return(this);
return this.target.unscoped().update(update, { ...options, where }).return(this);
}
/**
......
......@@ -80,10 +80,11 @@ class HasOne extends Association {
_injectAttributes() {
const newAttributes = {};
newAttributes[this.foreignKey] = _.defaults({}, this.foreignKeyAttribute, {
newAttributes[this.foreignKey] = {
type: this.options.keyType || this.source.rawAttributes[this.sourceKey].type,
allowNull: true
});
allowNull: true,
...this.foreignKeyAttribute
};
if (this.options.constraints !== false) {
const target = this.target.rawAttributes[this.foreignKey] || newAttributes[this.foreignKey];
......
......@@ -30,14 +30,15 @@ class ConnectionManager {
throw new Error('Support for pool:false was removed in v4.0');
}
config.pool = _.defaults(config.pool || {}, {
config.pool = {
max: 5,
min: 0,
idle: 10000,
acquire: 60000,
evict: 1000,
validate: this._validate.bind(this)
});
validate: this._validate.bind(this),
...config.pool
};
this.initPools();
}
......@@ -148,12 +149,19 @@ class ConnectionManager {
config.replication.read = [config.replication.read];
}
const configWithoutReplication = _.omit(this.config, 'replication');
// Map main connection config
config.replication.write = _.defaults(config.replication.write, _.omit(config, 'replication'));
config.replication.write = {
...configWithoutReplication,
...config.replication.write
};
// Apply defaults to each read config
config.replication.read = config.replication.read.map(readConfig =>
_.defaults(readConfig, _.omit(this.config, 'replication'))
config.replication.read = config.replication.read.map(readConfig => ({
...configWithoutReplication,
readConfig
})
);
// custom pooling for replication (original author @janmeier)
......
......@@ -101,8 +101,10 @@ class QueryGenerator {
* @private
*/
insertQuery(table, valueHash, modelAttributes, options) {
options = options || {};
_.defaults(options, this.options);
options = {
...this.options,
...options
};
const modelAttributeMap = {};
const fields = [];
......@@ -324,6 +326,7 @@ class QueryGenerator {
* @private
*/
updateQuery(tableName, attrValueHash, where, options, attributes) {
// TODO: Mutates argument, should be fixed!
options = options || {};
_.defaults(options, this.options);
......@@ -406,7 +409,10 @@ class QueryGenerator {
}
}
const whereOptions = _.defaults({ bindParam }, options);
const whereOptions = {
...options,
bindParam
};
if (values.length === 0) {
return '';
......@@ -432,8 +438,10 @@ class QueryGenerator {
* @param {Object} attributes
*/
arithmeticQuery(operator, tableName, attrValueHash, where, options, attributes) {
options = options || {};
_.defaults(options, { returning: true });
options = {
returning: true,
...options
};
attrValueHash = Utils.removeNullValuesFromHash(attrValueHash, this.options.omitNull);
......
......@@ -343,7 +343,10 @@ class PostgresQueryGenerator extends AbstractQueryGenerator {
upsertQuery(tableName, insertValues, updateValues, where, model, options) {
const primaryField = this.quoteIdentifier(model.primaryKeyField);
const upsertOptions = _.defaults({ bindParam: false }, options);
const upsertOptions = {
...options,
bindParam: false
};
const insert = this.insertQuery(tableName, insertValues, model.rawAttributes, upsertOptions);
const update = this.updateQuery(tableName, updateValues, where, upsertOptions, model.rawAttributes);
......
......@@ -204,9 +204,11 @@ class SQLiteQueryGenerator extends MySqlQueryGenerator {
options.ignoreDuplicates = true;
const bind = [];
const bindParam = this.bindParam(bind);
const upsertOptions = _.defaults({ bindParam }, options);
const upsertOptions = {
...options,
bindParam: this.bindParam(bind)
};
const insert = this.insertQuery(tableName, insertValues, model.rawAttributes, upsertOptions);
const update = this.updateQuery(tableName, updateValues, where, upsertOptions, model.rawAttributes);
......@@ -216,8 +218,10 @@ class SQLiteQueryGenerator extends MySqlQueryGenerator {
}
updateQuery(tableName, attrValueHash, where, options, attributes) {
options = options || {};
_.defaults(options, this.options);
options = {
...this.options,
...options
};
attrValueHash = Utils.removeNullValuesFromHash(attrValueHash, options.omitNull, options);
......@@ -246,7 +250,7 @@ class SQLiteQueryGenerator extends MySqlQueryGenerator {
}
let query;
const whereOptions = _.defaults({ bindParam }, options);
const whereOptions = { ...options, bindParam };
if (options.limit) {
query = `UPDATE ${this.quoteTable(tableName)} SET ${values.join(',')} WHERE rowid IN (SELECT rowid FROM ${this.quoteTable(tableName)} ${this.whereQuery(where, whereOptions)} LIMIT ${this.escape(options.limit)})`;
......@@ -264,8 +268,11 @@ class SQLiteQueryGenerator extends MySqlQueryGenerator {
].join('');
}
deleteQuery(tableName, where, options = {}, model) {
_.defaults(options, this.options);
deleteQuery(tableName, where, options, model) {
options = {
...this.options,
...options
};
let whereClause = this.getWhereConditions(where, null, model, options);
......
......@@ -25,10 +25,11 @@ class InstanceValidator {
}
// assign defined and default options
this.options = _.defaults(options, {
this.options = {
skip: [],
hooks: true
});
hooks: true,
...options
};
this.modelInstance = modelInstance;
......
......@@ -22,12 +22,8 @@ class ModelManager {
delete this.sequelize.models[modelToRemove.name];
}
getModel(against, options) {
options = _.defaults(options || {}, {
attribute: 'name'
});
return this.models.find(model => model[options.attribute] === against);
getModel(against, { attribute = 'name' } = {}) {
return this.models.find(model => model[attribute] === against);
}
get all() {
......@@ -48,9 +44,10 @@ class ModelManager {
let sorted;
let dep;
options = _.defaults(options || {}, {
reverse: true
});
options = {
reverse: true,
...options
};
for (const model of this.models) {
let deps = [];
......
......@@ -626,16 +626,16 @@ class Model {
if (!include.include) include.include = [];
const through = include.association.through;
include.through = _.defaults(include.through || {}, {
include.through = {
model: through.model,
as: through.model.name,
association: {
isSingleAssociation: true
},
_pseudo: true,
parent: include
});
parent: include,
...include.through
};
if (through.scope) {
include.through.where = include.through.where ? { [Op.and]: [include.through.where, through.scope] } : through.scope;
......@@ -763,10 +763,11 @@ class Model {
throw new Error('Missing "fields" property for index definition');
}
index = _.defaults(index, {
index = {
type: '',
parser: null
});
parser: null,
...index
};
if (index.type && index.type.toLowerCase() === 'unique') {
index.unique = true;
......@@ -1685,9 +1686,10 @@ class Model {
let originalOptions;
tableNames[this.getTableName(options)] = true;
options = Utils.cloneDeep(options);
_.defaults(options, { hooks: true });
options = {
hooks: true,
...Utils.cloneDeep(options)
};
// set rejectOnEmpty option, defaults to model options
options.rejectOnEmpty = options.hasOwnProperty('rejectOnEmpty')
......@@ -1913,9 +1915,10 @@ class Model {
}
// Bypass a possible overloaded findAll.
return this.findAll(_.defaults(options, {
plain: true
}));
return this.findAll({
plain: true,
...options
});
}
/**
......@@ -2012,7 +2015,10 @@ class Model {
*/
static count(options) {
return Promise.try(() => {
options = _.defaults(Utils.cloneDeep(options), { hooks: true });
options = {
hooks: true,
...options
};
if (options.hooks) {
return this.runHooks('beforeCount', options);
}
......@@ -2727,14 +2733,14 @@ class Model {
throw new Error('Expected plain object, array or sequelize method in the options.where parameter of model.destroy.');
}
options = _.defaults(options, {
options = {
hooks: true,
individualHooks: false,
force: false,
cascade: false,
restartIdentity: false
});
restartIdentity: false,
...options
};
options.type = QueryTypes.BULKDELETE;
Utils.mapOptionFieldNames(options, this);
......@@ -2882,14 +2888,15 @@ class Model {
this._injectScope(options);
this._optionsMustContainWhere(options);
options = this._paranoidClause(this, _.defaults(options, {
options = this._paranoidClause(this, {
validate: true,
hooks: true,
individualHooks: false,
returning: false,
force: false,
sideEffects: true
}));
sideEffects: true,
...options
});
options.type = QueryTypes.BULKUPDATE;
......@@ -3246,9 +3253,11 @@ class Model {
* @returns {Promise<Model[],?number>} returns an array of affected rows and affected count with `options.returning: true`, whenever supported by dialect
*/
static decrement(fields, options) {
options = _.defaults({ increment: false }, options, {
by: 1
});
options = {
by: 1,
...options,
increment: false
};
return this.increment(fields, options);
}
......@@ -3652,11 +3661,11 @@ class Model {
throw new Error('The second argument was removed in favor of the options object.');
}
options = Utils.cloneDeep(options);
options = _.defaults(options, {
options = {
hooks: true,
validate: true
});
validate: true,
...Utils.cloneDeep(options)
};
if (!options.fields) {
if (this.isNewRecord) {
......@@ -4039,7 +4048,7 @@ class Model {
this.setDataValue(field, values[field]);
return this.constructor.QueryInterface.update(
this, this.constructor.getTableName(options), values, where, _.defaults({ hooks: false, model: this.constructor }, options)
this, this.constructor.getTableName(options), values, where, { ...options, hooks: false, model: this.constructor }
).then(([results, rowsUpdated]) => {
if (this.constructor._versionAttribute && rowsUpdated < 1) {
throw new sequelizeErrors.OptimisticLockError({
......@@ -4188,9 +4197,11 @@ class Model {
* @returns {Promise}
*/
decrement(fields, options) {
options = _.defaults({ increment: false }, options, {
by: 1
});
options = {
by: 1,
...options,
increment: false
};
return this.increment(fields, options);
}
......
......@@ -1094,8 +1094,10 @@ class QueryInterface {
* @returns {Promise}
*/
bulkDelete(tableName, where, options, model) {
options = Utils.cloneDeep(options);
options = _.defaults(options, { limit: null });
options = {
limit: null,
...Utils.cloneDeep(options)
};
if (options.truncate === true) {
return this.sequelize.query(
......@@ -1104,7 +1106,7 @@ class QueryInterface {
);
}
if (typeof identifier === 'object') where = Utils.cloneDeep(where);
if (typeof where === 'object') where = Utils.cloneDeep(where);
return this.sequelize.query(
this.QueryGenerator.deleteQuery(tableName, where, options, model),
......@@ -1146,12 +1148,12 @@ class QueryInterface {
}
rawSelect(tableName, options, attributeSelector, Model) {
options = Utils.cloneDeep(options);
options = _.defaults(options, {
options = {
raw: true,
plain: true,
type: QueryTypes.SELECT
});
type: QueryTypes.SELECT,
...Utils.cloneDeep(options)
};
const sql = this.QueryGenerator.selectQuery(tableName, options, Model);
......
......@@ -544,11 +544,12 @@ class Sequelize {
options.fieldMap = _.get(options, 'model.fieldAttributeMap', {});
}
options = _.defaults(options, {
options = {
// eslint-disable-next-line no-console
logging: this.options.hasOwnProperty('logging') ? this.options.logging : console.log,
searchPath: this.options.hasOwnProperty('searchPath') ? this.options.searchPath : 'DEFAULT'
});
searchPath: this.options.hasOwnProperty('searchPath') ? this.options.searchPath : 'DEFAULT',
...options
};
if (!options.type) {
if (options.model || options.nest || options.plain) {
......@@ -771,9 +772,12 @@ class Sequelize {
* @returns {Promise}
*/
sync(options) {
options = { ...options };
options = {
...this.options,
...this.options.sync,
...options
};
options.hooks = options.hooks === undefined ? true : !!options.hooks;
options = _.defaults(options, this.options.sync, this.options);
if (options.match) {
if (!options.match.test(this.config.database)) {
......
......@@ -2,7 +2,6 @@
const fs = require('fs');
const path = require('path');
const _ = require('lodash');
const Sequelize = require('../index');
const Config = require('./config/config');
const chai = require('chai');
......@@ -55,14 +54,15 @@ const Support = {
const config = Config[options.dialect];
const sequelizeOptions = _.defaults(options, {
const sequelizeOptions = {
host: options.host || config.host,
logging: process.env.SEQ_LOG ? console.log : false,
dialect: options.dialect,
port: options.port || process.env.SEQ_PORT || config.port,
pool: config.pool,
dialectOptions: options.dialectOptions || config.dialectOptions || {}
});
dialectOptions: options.dialectOptions || config.dialectOptions || {},
...options
};
if (process.env.DIALECT === 'postgres-native') {
sequelizeOptions.native = true;
......
......@@ -86,23 +86,29 @@ describe(Support.getTestDialectTeaser('SQL'), () => {
if (current.dialect.name === 'postgres') {
describe('IF NOT EXISTS version check', () => {
const modifiedSQL = { ...sql };
const createTableQueryModified = sql.createTableQuery.bind(modifiedSQL);
let backup;
before(() => {
backup = sql.sequelize.options.databaseVersion;
});
after(() => {
sql.sequelize.options.databaseVersion = backup;
});
it('it will not have IF NOT EXISTS for version 9.0 or below', () => {
modifiedSQL.sequelize.options.databaseVersion = '9.0.0';
expectsql(createTableQueryModified(FooUser.getTableName(), sql.attributesToSQL(FooUser.rawAttributes), { }), {
sql.sequelize.options.databaseVersion = '9.0.0';
expectsql(sql.createTableQuery(FooUser.getTableName(), sql.attributesToSQL(FooUser.rawAttributes), { }), {
postgres: 'CREATE TABLE "foo"."users" ("id" SERIAL , "mood" "foo"."enum_users_mood", PRIMARY KEY ("id"));'
});
});
it('it will have IF NOT EXISTS for version 9.1 or above', () => {
modifiedSQL.sequelize.options.databaseVersion = '9.1.0';
expectsql(createTableQueryModified(FooUser.getTableName(), sql.attributesToSQL(FooUser.rawAttributes), { }), {
sql.sequelize.options.databaseVersion = '9.1.0';
expectsql(sql.createTableQuery(FooUser.getTableName(), sql.attributesToSQL(FooUser.rawAttributes), { }), {
postgres: 'CREATE TABLE IF NOT EXISTS "foo"."users" ("id" SERIAL , "mood" "foo"."enum_users_mood", PRIMARY KEY ("id"));'
});
});
it('it will have IF NOT EXISTS for default version', () => {
modifiedSQL.sequelize.options.databaseVersion = 0;
expectsql(createTableQueryModified(FooUser.getTableName(), sql.attributesToSQL(FooUser.rawAttributes), { }), {
sql.sequelize.options.databaseVersion = 0;
expectsql(sql.createTableQuery(FooUser.getTableName(), sql.attributesToSQL(FooUser.rawAttributes), { }), {
postgres: 'CREATE TABLE IF NOT EXISTS "foo"."users" ("id" SERIAL , "mood" "foo"."enum_users_mood", PRIMARY KEY ("id"));'
});
});
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!