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

Commit 33ff3ad5 by Ruben Bridgewater

Remove unnecessary indentation

1 parent 073f1777
var Association = function() { var Association = function () {};
};
module.exports = Association; module.exports = Association;
\ No newline at end of file
...@@ -6,176 +6,174 @@ var Utils = require('./../utils') ...@@ -6,176 +6,174 @@ var Utils = require('./../utils')
, Association = require('./base') , Association = require('./base')
, util = require('util'); , util = require('util');
module.exports = (function() { var BelongsTo = function(source, target, options) {
var BelongsTo = function(source, target, options) { Association.call(this);
Association.call(this);
this.associationType = 'BelongsTo';
this.associationType = 'BelongsTo'; this.source = source;
this.source = source; this.target = target;
this.target = target; this.options = options;
this.options = options; this.scope = options.scope;
this.scope = options.scope; this.isSingleAssociation = true;
this.isSingleAssociation = true; this.isSelfAssociation = (this.source === this.target);
this.isSelfAssociation = (this.source === this.target); this.as = this.options.as;
this.as = this.options.as;
if (Utils._.isObject(this.options.foreignKey)) {
if (Utils._.isObject(this.options.foreignKey)) { this.foreignKeyAttribute = this.options.foreignKey;
this.foreignKeyAttribute = this.options.foreignKey; this.foreignKey = this.foreignKeyAttribute.name || this.foreignKeyAttribute.fieldName;
this.foreignKey = this.foreignKeyAttribute.name || this.foreignKeyAttribute.fieldName; } else {
} else { this.foreignKeyAttribute = {};
this.foreignKeyAttribute = {}; this.foreignKey = this.options.foreignKey;
this.foreignKey = this.options.foreignKey; }
}
if (this.as) {
if (this.as) { this.isAliased = true;
this.isAliased = true; this.options.name = {
this.options.name = { singular: this.as
singular: this.as };
}; } else {
} else { this.as = this.target.options.name.singular;
this.as = this.target.options.name.singular; this.options.name = this.target.options.name;
this.options.name = this.target.options.name; }
}
if (!this.options.foreignKey) {
this.options.foreignKey = Utils._.camelizeIf(
[
Utils._.underscoredIf(this.as, this.source.options.underscored),
this.target.primaryKeyAttribute
].join('_'),
!this.source.options.underscored
);
}
this.identifier = this.foreignKey || Utils._.camelizeIf( if (!this.options.foreignKey) {
this.options.foreignKey = Utils._.camelizeIf(
[ [
Utils._.underscoredIf(this.options.name.singular, this.target.options.underscored), Utils._.underscoredIf(this.as, this.source.options.underscored),
this.target.primaryKeyAttribute this.target.primaryKeyAttribute
].join('_'), ].join('_'),
!this.target.options.underscored !this.source.options.underscored
); );
}
this.targetIdentifier = this.target.primaryKeyAttribute;
this.associationAccessor = this.as; this.identifier = this.foreignKey || Utils._.camelizeIf(
this.options.useHooks = options.useHooks; [
Utils._.underscoredIf(this.options.name.singular, this.target.options.underscored),
// Get singular name, trying to uppercase the first letter, unless the model forbids it this.target.primaryKeyAttribute
var singular = Utils.uppercaseFirst(this.options.name.singular); ].join('_'),
!this.target.options.underscored
this.accessors = { );
get: 'get' + singular,
set: 'set' + singular, this.targetIdentifier = this.target.primaryKeyAttribute;
create: 'create' + singular this.associationAccessor = this.as;
}; this.options.useHooks = options.useHooks;
// Get singular name, trying to uppercase the first letter, unless the model forbids it
var singular = Utils.uppercaseFirst(this.options.name.singular);
this.accessors = {
get: 'get' + singular,
set: 'set' + singular,
create: 'create' + singular
}; };
};
util.inherits(BelongsTo, Association); util.inherits(BelongsTo, Association);
// the id is in the source table // the id is in the source table
BelongsTo.prototype.injectAttributes = function() { BelongsTo.prototype.injectAttributes = function() {
var newAttributes = {}; var newAttributes = {};
newAttributes[this.identifier] = Utils._.defaults(this.foreignKeyAttribute, { type: this.options.keyType || this.target.rawAttributes[this.targetIdentifier].type }); newAttributes[this.identifier] = Utils._.defaults(this.foreignKeyAttribute, { type: this.options.keyType || this.target.rawAttributes[this.targetIdentifier].type });
if (this.options.constraints !== false) { if (this.options.constraints !== false) {
this.options.onDelete = this.options.onDelete || 'SET NULL'; this.options.onDelete = this.options.onDelete || 'SET NULL';
this.options.onUpdate = this.options.onUpdate || 'CASCADE'; this.options.onUpdate = this.options.onUpdate || 'CASCADE';
} }
Helpers.addForeignKeyConstraints(newAttributes[this.identifier], this.target, this.source, this.options); Helpers.addForeignKeyConstraints(newAttributes[this.identifier], this.target, this.source, this.options);
Utils.mergeDefaults(this.source.rawAttributes, newAttributes); Utils.mergeDefaults(this.source.rawAttributes, newAttributes);
this.identifierField = this.source.rawAttributes[this.identifier].field || this.identifier; this.identifierField = this.source.rawAttributes[this.identifier].field || this.identifier;
this.source.refreshAttributes(); this.source.refreshAttributes();
Helpers.checkNamingCollision(this); Helpers.checkNamingCollision(this);
return this; return this;
}; };
// Add getAssociation method to the prototype of the model instance // Add getAssociation method to the prototype of the model instance
BelongsTo.prototype.injectGetter = function(instancePrototype) { BelongsTo.prototype.injectGetter = function(instancePrototype) {
var association = this; var association = this;
instancePrototype[this.accessors.get] = function(options) { instancePrototype[this.accessors.get] = function(options) {
var where = {}; var where = {};
where[association.targetIdentifier] = this.get(association.identifier); where[association.targetIdentifier] = this.get(association.identifier);
options = association.target.__optClone(options) || {}; options = association.target.__optClone(options) || {};
options.where = { options.where = {
$and: [ $and: [
options.where, options.where,
where where
] ]
}; };
if (options.limit === undefined) options.limit = null; if (options.limit === undefined) options.limit = null;
var model = association.target; var model = association.target;
if (options.hasOwnProperty('scope')) { if (options.hasOwnProperty('scope')) {
if (!options.scope) { if (!options.scope) {
model = model.unscoped(); model = model.unscoped();
} else { } else {
model = model.scope(options.scope); model = model.scope(options.scope);
}
} }
}
return model.find(options); return model.find(options);
};
return this;
}; };
// Add setAssociaton method to the prototype of the model instance return this;
BelongsTo.prototype.injectSetter = function(instancePrototype) { };
var association = this;
instancePrototype[this.accessors.set] = function(associatedInstance, options) { // Add setAssociaton method to the prototype of the model instance
options = options || {}; BelongsTo.prototype.injectSetter = function(instancePrototype) {
var association = this;
var value = associatedInstance; instancePrototype[this.accessors.set] = function(associatedInstance, options) {
if (associatedInstance instanceof association.target.Instance) { options = options || {};
value = associatedInstance[association.targetIdentifier];
}
this.set(association.identifier, value); var value = associatedInstance;
if (associatedInstance instanceof association.target.Instance) {
value = associatedInstance[association.targetIdentifier];
}
if (options.save === false) return; this.set(association.identifier, value);
options = Utils._.extend({ if (options.save === false) return;
fields: [association.identifier],
allowNull: [association.identifier],
association: true
}, options);
options = Utils._.extend({
fields: [association.identifier],
allowNull: [association.identifier],
association: true
}, options);
// passes the changed field to save, so only that field get updated.
return this.save(options);
};
return this; // passes the changed field to save, so only that field get updated.
return this.save(options);
}; };
// Add createAssociation method to the prototype of the model instance return this;
BelongsTo.prototype.injectCreator = function(instancePrototype) { };
var association = this;
instancePrototype[this.accessors.create] = function(values, fieldsOrOptions) { // Add createAssociation method to the prototype of the model instance
var instance = this BelongsTo.prototype.injectCreator = function(instancePrototype) {
, options = {}; var association = this;
if ((fieldsOrOptions || {}).transaction instanceof Transaction) { instancePrototype[this.accessors.create] = function(values, fieldsOrOptions) {
options.transaction = fieldsOrOptions.transaction; var instance = this
} , options = {};
options.logging = (fieldsOrOptions || {}).logging;
return association.target.create(values, fieldsOrOptions).then(function(newAssociatedObject) { if ((fieldsOrOptions || {}).transaction instanceof Transaction) {
return instance[association.accessors.set](newAssociatedObject, options); options.transaction = fieldsOrOptions.transaction;
}); }
}; options.logging = (fieldsOrOptions || {}).logging;
return this; return association.target.create(values, fieldsOrOptions).then(function(newAssociatedObject) {
return instance[association.accessors.set](newAssociatedObject, options);
});
}; };
return BelongsTo; return this;
})(); };
module.exports = BelongsTo;
...@@ -3,135 +3,133 @@ ...@@ -3,135 +3,133 @@
var Utils = require('./../utils') var Utils = require('./../utils')
, _ = require('lodash'); , _ = require('lodash');
module.exports = (function() { var HasManySingleLinked = function(association, instance) {
var HasManySingleLinked = function(association, instance) { this.association = association;
this.association = association; this.instance = instance;
this.instance = instance; this.target = this.association.target;
this.target = this.association.target; this.source = this.association.source;
this.source = this.association.source; };
HasManySingleLinked.prototype.injectGetter = function(options) {
var scopeWhere = this.association.scope ? {} : null;
if (this.association.scope) {
Object.keys(this.association.scope).forEach(function (attribute) {
scopeWhere[attribute] = this.association.scope[attribute];
}.bind(this));
}
options.where = {
$and: [
new Utils.where(
this.target.rawAttributes[this.association.identifier],
this.instance[this.source.primaryKeyAttribute]
),
scopeWhere,
options.where
]
}; };
HasManySingleLinked.prototype.injectGetter = function(options) { var model = this.association.target;
var scopeWhere = this.association.scope ? {} : null; if (options.hasOwnProperty('scope')) {
if (!options.scope) {
model = model.unscoped();
} else {
model = model.scope(options.scope);
}
}
return model.all(options);
};
HasManySingleLinked.prototype.injectSetter = function(oldAssociations, newAssociations, defaultAttributes) {
var self = this
, primaryKeys
, primaryKey
, updateWhere
, associationKeys = Object.keys((oldAssociations[0] || newAssociations[0] || {Model: {primaryKeys: {}}}).Model.primaryKeys || {})
, associationKey = (associationKeys.length === 1) ? associationKeys[0] : 'id'
, options = defaultAttributes
, promises = []
, obsoleteAssociations = oldAssociations.filter(function(old) {
return !Utils._.find(newAssociations, function(obj) {
return obj[associationKey] === old[associationKey];
});
})
, unassociatedObjects = newAssociations.filter(function(obj) {
return !Utils._.find(oldAssociations, function(old) {
return obj[associationKey] === old[associationKey];
});
})
, update;
if (obsoleteAssociations.length > 0) {
// clear the old associations
var obsoleteIds = obsoleteAssociations.map(function(associatedObject) {
associatedObject[self.association.identifier] = (newAssociations.length < 1 ? null : self.instance.id);
return associatedObject[associationKey];
});
update = {};
update[self.association.identifier] = null;
primaryKeys = Object.keys(this.association.target.primaryKeys);
primaryKey = primaryKeys.length === 1 ? primaryKeys[0] : 'id';
updateWhere = {};
updateWhere[primaryKey] = obsoleteIds;
promises.push(this.association.target.unscoped().update(
update,
Utils._.extend(options, {
allowNull: [self.association.identifier],
where: updateWhere
})
));
}
if (unassociatedObjects.length > 0) {
// For the self.instance
var pkeys = Object.keys(self.instance.Model.primaryKeys)
, pkey = pkeys.length === 1 ? pkeys[0] : 'id';
primaryKeys = Object.keys(this.association.target.primaryKeys);
primaryKey = primaryKeys.length === 1 ? primaryKeys[0] : 'id';
updateWhere = {};
// set the new associations
var unassociatedIds = unassociatedObjects.map(function(associatedObject) {
associatedObject[self.association.identifier] = self.instance[pkey] || self.instance.id;
return associatedObject[associationKey];
});
update = {};
update[self.association.identifier] = (newAssociations.length < 1 ? null : self.instance[pkey] || self.instance.id);
if (this.association.scope) { if (this.association.scope) {
Object.keys(this.association.scope).forEach(function (attribute) { _.assign(update, this.association.scope);
scopeWhere[attribute] = this.association.scope[attribute];
}.bind(this));
} }
options.where = { updateWhere[primaryKey] = unassociatedIds;
$and: [
new Utils.where(
this.target.rawAttributes[this.association.identifier],
this.instance[this.source.primaryKeyAttribute]
),
scopeWhere,
options.where
]
};
var model = this.association.target;
if (options.hasOwnProperty('scope')) {
if (!options.scope) {
model = model.unscoped();
} else {
model = model.scope(options.scope);
}
}
return model.all(options); promises.push(this.association.target.unscoped().update(
}; update,
Utils._.extend(options, {
allowNull: [self.association.identifier],
where: updateWhere
})
));
}
HasManySingleLinked.prototype.injectSetter = function(oldAssociations, newAssociations, defaultAttributes) { return Utils.Promise.all(promises);
var self = this };
, primaryKeys
, primaryKey
, updateWhere
, associationKeys = Object.keys((oldAssociations[0] || newAssociations[0] || {Model: {primaryKeys: {}}}).Model.primaryKeys || {})
, associationKey = (associationKeys.length === 1) ? associationKeys[0] : 'id'
, options = defaultAttributes
, promises = []
, obsoleteAssociations = oldAssociations.filter(function(old) {
return !Utils._.find(newAssociations, function(obj) {
return obj[associationKey] === old[associationKey];
});
})
, unassociatedObjects = newAssociations.filter(function(obj) {
return !Utils._.find(oldAssociations, function(old) {
return obj[associationKey] === old[associationKey];
});
})
, update;
if (obsoleteAssociations.length > 0) {
// clear the old associations
var obsoleteIds = obsoleteAssociations.map(function(associatedObject) {
associatedObject[self.association.identifier] = (newAssociations.length < 1 ? null : self.instance.id);
return associatedObject[associationKey];
});
update = {};
update[self.association.identifier] = null;
primaryKeys = Object.keys(this.association.target.primaryKeys);
primaryKey = primaryKeys.length === 1 ? primaryKeys[0] : 'id';
updateWhere = {};
updateWhere[primaryKey] = obsoleteIds;
promises.push(this.association.target.unscoped().update(
update,
Utils._.extend(options, {
allowNull: [self.association.identifier],
where: updateWhere
})
));
}
if (unassociatedObjects.length > 0) { HasManySingleLinked.prototype.injectAdder = function(newAssociation, options) {
// For the self.instance newAssociation.set(this.association.identifier, this.instance.get(this.instance.Model.primaryKeyAttribute));
var pkeys = Object.keys(self.instance.Model.primaryKeys) if (this.association.scope) {
, pkey = pkeys.length === 1 ? pkeys[0] : 'id'; Object.keys(this.association.scope).forEach(function (attribute) {
newAssociation.set(attribute, this.association.scope[attribute]);
primaryKeys = Object.keys(this.association.target.primaryKeys); }.bind(this));
primaryKey = primaryKeys.length === 1 ? primaryKeys[0] : 'id'; }
updateWhere = {};
// set the new associations
var unassociatedIds = unassociatedObjects.map(function(associatedObject) {
associatedObject[self.association.identifier] = self.instance[pkey] || self.instance.id;
return associatedObject[associationKey];
});
update = {};
update[self.association.identifier] = (newAssociations.length < 1 ? null : self.instance[pkey] || self.instance.id);
if (this.association.scope) {
_.assign(update, this.association.scope);
}
updateWhere[primaryKey] = unassociatedIds;
promises.push(this.association.target.unscoped().update(
update,
Utils._.extend(options, {
allowNull: [self.association.identifier],
where: updateWhere
})
));
}
return Utils.Promise.all(promises); return newAssociation.save(options);
}; };
HasManySingleLinked.prototype.injectAdder = function(newAssociation, options) {
newAssociation.set(this.association.identifier, this.instance.get(this.instance.Model.primaryKeyAttribute));
if (this.association.scope) {
Object.keys(this.association.scope).forEach(function (attribute) {
newAssociation.set(attribute, this.association.scope[attribute]);
}.bind(this));
}
return newAssociation.save(options);
};
return HasManySingleLinked; module.exports = HasManySingleLinked;
})();
...@@ -2,48 +2,50 @@ ...@@ -2,48 +2,50 @@
var Utils = require('./../utils'); var Utils = require('./../utils');
module.exports = { function checkNamingCollision (association) {
checkNamingCollision: function (association) { if (association.source.rawAttributes.hasOwnProperty(association.as)) {
if (association.source.rawAttributes.hasOwnProperty(association.as)) { throw new Error(
throw new Error( 'Naming collision between attribute \'' + association.as +
'Naming collision between attribute \'' + association.as + '\' and association \'' + association.as + '\' on model ' + association.source.name +
'\' and association \'' + association.as + '\' on model ' + association.source.name + '. To remedy this, change either foreignKey or as in your association definition'
'. To remedy this, change either foreignKey or as in your association definition' );
); }
} }
},
function addForeignKeyConstraints (newAttribute, source, target, options) {
addForeignKeyConstraints: function(newAttribute, source, target, options) { // FK constraints are opt-in: users must either set `foreignKeyConstraints`
// FK constraints are opt-in: users must either set `foreignKeyConstraints` // on the association, or request an `onDelete` or `onUpdate` behaviour
// on the association, or request an `onDelete` or `onUpdate` behaviour
if (options.foreignKeyConstraint || options.onDelete || options.onUpdate) {
if (options.foreignKeyConstraint || options.onDelete || options.onUpdate) {
// Find primary keys: composite keys not supported with this approach
// Find primary keys: composite keys not supported with this approach var primaryKeys = Utils._.chain(source.rawAttributes).keys()
var primaryKeys = Utils._.chain(source.rawAttributes).keys() .filter(function(key) { return source.rawAttributes[key].primaryKey; })
.filter(function(key) { return source.rawAttributes[key].primaryKey; }) .map(function(key) { return source.rawAttributes[key].field || key; }).value();
.map(function(key) { return source.rawAttributes[key].field || key; }).value();
if (primaryKeys.length === 1) {
if (primaryKeys.length === 1) { if (!!source.options.schema) {
if (!!source.options.schema) { newAttribute.references = {
newAttribute.references = { model: source.modelManager.sequelize.queryInterface.QueryGenerator.addSchema({
model: source.modelManager.sequelize.queryInterface.QueryGenerator.addSchema({ tableName: source.tableName,
tableName: source.tableName, options: {
options: { schema: source.options.schema,
schema: source.options.schema, schemaDelimiter: source.options.schemaDelimiter
schemaDelimiter: source.options.schemaDelimiter }
} })
}) };
}; } else {
} else { newAttribute.references = { model: source.tableName };
newAttribute.references = { model: source.tableName };
}
newAttribute.references.key = primaryKeys[0];
newAttribute.onDelete = options.onDelete;
newAttribute.onUpdate = options.onUpdate;
} }
newAttribute.references.key = primaryKeys[0];
newAttribute.onDelete = options.onDelete;
newAttribute.onUpdate = options.onUpdate;
} }
} }
}
module.exports = {
checkNamingCollision: checkNamingCollision,
addForeignKeyConstraints: addForeignKeyConstraints
}; };
This diff could not be displayed because it is too large.
...@@ -2,15 +2,17 @@ ...@@ -2,15 +2,17 @@
var hstore = require('pg-hstore')({sanitize : true}); var hstore = require('pg-hstore')({sanitize : true});
module.exports = { function stringify (data) {
stringify: function(data) { if (data === null) return null;
if(data === null) return null;
return hstore.stringify(data); return hstore.stringify(data);
}, }
parse: function(value) {
if(value === null) return null;
function parse (value) {
if (value === null) return null;
return hstore.parse(value); return hstore.parse(value);
} }
module.exports = {
stringify: stringify,
parse: parse
}; };
...@@ -3,60 +3,64 @@ ...@@ -3,60 +3,64 @@
var Utils = require('../../utils'), var Utils = require('../../utils'),
moment = require('moment'); moment = require('moment');
module.exports = { function stringify (data) {
stringify: function (data) { if (data === null) return null;
if (data === null) return null;
if (!Utils._.isArray(data) || data.length !== 2) return '';
if (!Utils._.isArray(data) || data.length !== 2) return ''; if (Utils._.any(data, Utils._.isNull)) return '';
if (Utils._.any(data, Utils._.isNull)) return ''; if (data.hasOwnProperty('inclusive')) {
if (!data.inclusive) data.inclusive = [false, false];
else if (data.inclusive === true) data.inclusive = [true, true];
} else {
data.inclusive = [false, false];
}
if (data.hasOwnProperty('inclusive')) { Utils._.each(data, function (value, index) {
if (!data.inclusive) data.inclusive = [false, false]; if (Utils._.isObject(value)) {
else if (data.inclusive === true) data.inclusive = [true, true]; if (value.hasOwnProperty('inclusive')) data.inclusive[index] = !!value.inclusive;
} else { if (value.hasOwnProperty('value')) data[index] = value.value;
data.inclusive = [false, false];
} }
});
return (data.inclusive[0] ? '[' : '(') + JSON.stringify(data[0]) + ',' + JSON.stringify(data[1]) + (data.inclusive[1] ? ']' : ')');
}
function parse (value, AttributeType) {
if (value === null) return null;
if(typeof AttributeType === 'function') AttributeType = new AttributeType();
AttributeType = AttributeType || ''; // if attribute is not defined, assign empty string in order to prevent
// AttributeType.toString() to fail with uncaught exception later in the code
var result = value
.substring(1, value.length - 1)
.split(',', 2);
Utils._.each(data, function (value, index) { if (result.length !== 2) return value;
if (Utils._.isObject(value)) {
if (value.hasOwnProperty('inclusive')) data.inclusive[index] = !!value.inclusive; result = result
if (value.hasOwnProperty('value')) data[index] = value.value; .map(function (value) {
switch (AttributeType.toString()) {
case 'int4range':
return parseInt(value, 10);
case 'numrange':
return parseFloat(value);
case 'daterange':
case 'tsrange':
case 'tstzrange':
return moment(value).toDate();
} }
return value;
}); });
return (data.inclusive[0] ? '[' : '(') + JSON.stringify(data[0]) + ',' + JSON.stringify(data[1]) + (data.inclusive[1] ? ']' : ')'); result.inclusive = [(value[0] === '['), (value[value.length - 1] === ']')];
},
parse: function (value, AttributeType) { return result;
if (value === null) return null; }
if(typeof AttributeType === 'function') AttributeType = new AttributeType(); module.exports = {
AttributeType = AttributeType || ''; // if attribute is not defined, assign empty string in order to prevent stringify: stringify,
// AttributeType.toString() to fail with uncaught exception later in the code parse: parse
var result = value
.substring(1, value.length - 1)
.split(',', 2);
if (result.length !== 2) return value;
result = result
.map(function (value) {
switch (AttributeType.toString()) {
case 'int4range':
return parseInt(value, 10);
case 'numrange':
return parseFloat(value);
case 'daterange':
case 'tsrange':
case 'tstzrange':
return moment(value).toDate();
}
return value;
});
result.inclusive = [(value[0] === '['), (value[value.length - 1] === ']')];
return result;
}
}; };
...@@ -9,106 +9,111 @@ var Utils = require('../../utils') ...@@ -9,106 +9,111 @@ var Utils = require('../../utils')
@class QueryInterface @class QueryInterface
@static @static
*/ */
module.exports = {
/** /**
A wrapper that fixes SQLite's inability to remove columns from existing tables. A wrapper that fixes SQLite's inability to remove columns from existing tables.
It will create a backup of the table, drop the table afterwards and create a It will create a backup of the table, drop the table afterwards and create a
new table with the same name but without the obsolete column. new table with the same name but without the obsolete column.
@method removeColumn @method removeColumn
@for QueryInterface @for QueryInterface
@param {String} tableName The name of the table. @param {String} tableName The name of the table.
@param {String} attributeName The name of the attribute that we want to remove. @param {String} attributeName The name of the attribute that we want to remove.
@param {Object} options @param {Object} options
@param {Boolean|Function} [options.logging] A function that logs the sql queries, or false for explicitly not logging these queries @param {Boolean|Function} [options.logging] A function that logs the sql queries, or false for explicitly not logging these queries
@param {CustomEventEmitter} emitter The EventEmitter from outside. @param {CustomEventEmitter} emitter The EventEmitter from outside.
@param {Function} queryAndEmit The function from outside that triggers some events to get triggered. @param {Function} queryAndEmit The function from outside that triggers some events to get triggered.
@since 1.6.0 @since 1.6.0
*/ */
removeColumn: function(tableName, attributeName, options) { var removeColumn = function(tableName, attributeName, options) {
var self = this; var self = this;
options = options || {}; options = options || {};
return this.describeTable(tableName).then(function(fields) { return this.describeTable(tableName).then(function(fields) {
delete fields[attributeName]; delete fields[attributeName];
var sql = self.QueryGenerator.removeColumnQuery(tableName, fields) var sql = self.QueryGenerator.removeColumnQuery(tableName, fields)
, subQueries = sql.split(';').filter(function(q) { return q !== ''; }); , subQueries = sql.split(';').filter(function(q) { return q !== ''; });
return Promise.each(subQueries, function(subQuery) { return Promise.each(subQueries, function(subQuery) {
return self.sequelize.query(subQuery + ';', { raw: true, logging: options.logging }); return self.sequelize.query(subQuery + ';', { raw: true, logging: options.logging });
});
}); });
}, });
};
/**
A wrapper that fixes SQLite's inability to change columns from existing tables. /**
It will create a backup of the table, drop the table afterwards and create a A wrapper that fixes SQLite's inability to change columns from existing tables.
new table with the same name but with a modified version of the respective column. It will create a backup of the table, drop the table afterwards and create a
new table with the same name but with a modified version of the respective column.
@method changeColumn
@for QueryInterface @method changeColumn
@for QueryInterface
@param {String} tableName The name of the table.
@param {Object} attributes An object with the attribute's name as key and it's options as value object. @param {String} tableName The name of the table.
@param {Object} options @param {Object} attributes An object with the attribute's name as key and it's options as value object.
@param {Boolean|Function} [options.logging] A function that logs the sql queries, or false for explicitly not logging these queries @param {Object} options
@param {CustomEventEmitter} emitter The EventEmitter from outside. @param {Boolean|Function} [options.logging] A function that logs the sql queries, or false for explicitly not logging these queries
@param {Function} queryAndEmit The function from outside that triggers some events to get triggered. @param {CustomEventEmitter} emitter The EventEmitter from outside.
@param {Function} queryAndEmit The function from outside that triggers some events to get triggered.
@since 1.6.0
*/ @since 1.6.0
changeColumn: function(tableName, attributes, options) { */
var attributeName = Utils._.keys(attributes)[0] var changeColumn = function(tableName, attributes, options) {
, self = this; var attributeName = Utils._.keys(attributes)[0]
options = options || {}; , self = this;
options = options || {};
return this.describeTable(tableName).then(function(fields) {
fields[attributeName] = attributes[attributeName]; return this.describeTable(tableName).then(function(fields) {
fields[attributeName] = attributes[attributeName];
var sql = self.QueryGenerator.removeColumnQuery(tableName, fields)
, subQueries = sql.split(';').filter(function(q) { return q !== ''; }); var sql = self.QueryGenerator.removeColumnQuery(tableName, fields)
, subQueries = sql.split(';').filter(function(q) { return q !== ''; });
return Promise.each(subQueries, function(subQuery) {
return self.sequelize.query(subQuery + ';', { raw: true, logging: options.logging }); return Promise.each(subQueries, function(subQuery) {
}); return self.sequelize.query(subQuery + ';', { raw: true, logging: options.logging });
}); });
}, });
};
/**
A wrapper that fixes SQLite's inability to rename columns from existing tables. /**
It will create a backup of the table, drop the table afterwards and create a A wrapper that fixes SQLite's inability to rename columns from existing tables.
new table with the same name but with a renamed version of the respective column. It will create a backup of the table, drop the table afterwards and create a
new table with the same name but with a renamed version of the respective column.
@method renameColumn
@for QueryInterface @method renameColumn
@for QueryInterface
@param {String} tableName The name of the table.
@param {String} attrNameBefore The name of the attribute before it was renamed. @param {String} tableName The name of the table.
@param {String} attrNameAfter The name of the attribute after it was renamed. @param {String} attrNameBefore The name of the attribute before it was renamed.
@param {Object} options @param {String} attrNameAfter The name of the attribute after it was renamed.
@param {Boolean|Function} [options.logging] A function that logs the sql queries, or false for explicitly not logging these queries @param {Object} options
@param {CustomEventEmitter} emitter The EventEmitter from outside. @param {Boolean|Function} [options.logging] A function that logs the sql queries, or false for explicitly not logging these queries
@param {Function} queryAndEmit The function from outside that triggers some events to get triggered. @param {CustomEventEmitter} emitter The EventEmitter from outside.
@param {Function} queryAndEmit The function from outside that triggers some events to get triggered.
@since 1.6.0
*/ @since 1.6.0
renameColumn: function(tableName, attrNameBefore, attrNameAfter, options) { */
var self = this; var renameColumn = function(tableName, attrNameBefore, attrNameAfter, options) {
options = options || {}; var self = this;
options = options || {};
return this.describeTable(tableName).then(function(fields) {
fields[attrNameAfter] = Utils._.clone(fields[attrNameBefore]); return this.describeTable(tableName).then(function(fields) {
delete fields[attrNameBefore]; fields[attrNameAfter] = Utils._.clone(fields[attrNameBefore]);
delete fields[attrNameBefore];
var sql = self.QueryGenerator.renameColumnQuery(tableName, attrNameBefore, attrNameAfter, fields)
, subQueries = sql.split(';').filter(function(q) { return q !== ''; }); var sql = self.QueryGenerator.renameColumnQuery(tableName, attrNameBefore, attrNameAfter, fields)
, subQueries = sql.split(';').filter(function(q) { return q !== ''; });
return Promise.each(subQueries, function(subQuery) {
return self.sequelize.query(subQuery + ';', { raw: true, logging: options.logging }); return Promise.each(subQueries, function(subQuery) {
}); return self.sequelize.query(subQuery + ';', { raw: true, logging: options.logging });
}); });
} });
}; };
module.exports = {
removeColumn: removeColumn,
changeColumn: changeColumn,
renameColumn: renameColumn
};
\ No newline at end of file
...@@ -4,100 +4,98 @@ var Toposort = require('toposort-class') ...@@ -4,100 +4,98 @@ var Toposort = require('toposort-class')
, Utils = require('./utils') , Utils = require('./utils')
, _ = require('lodash'); , _ = require('lodash');
module.exports = (function() { var ModelManager = function(sequelize) {
var ModelManager = function(sequelize) { this.models = [];
this.models = []; this.sequelize = sequelize;
this.sequelize = sequelize; };
};
ModelManager.prototype.addModel = function(model) {
this.models.push(model);
this.sequelize.models[model.name] = model;
return model;
};
ModelManager.prototype.removeModel = function(model) {
this.models = this.models.filter(function($model) {
return $model.name !== model.name;
});
delete this.sequelize.models[model.name]; ModelManager.prototype.addModel = function(model) {
}; this.models.push(model);
this.sequelize.models[model.name] = model;
ModelManager.prototype.getModel = function(against, options) { return model;
options = _.defaults(options || {}, { };
attribute: 'name'
});
var model = this.models.filter(function(model) { ModelManager.prototype.removeModel = function(model) {
return model[options.attribute] === against; this.models = this.models.filter(function($model) {
}); return $model.name !== model.name;
});
return !!model ? model[0] : null; delete this.sequelize.models[model.name];
}; };
ModelManager.prototype.__defineGetter__('all', function() { ModelManager.prototype.getModel = function(against, options) {
return this.models; options = _.defaults(options || {}, {
attribute: 'name'
}); });
/** var model = this.models.filter(function(model) {
* Iterate over Models in an order suitable for e.g. creating tables. Will return model[options.attribute] === against;
* take foreign key constraints into account so that dependencies are visited });
* before dependents.
*/
ModelManager.prototype.forEachModel = function(iterator, options) {
var models = {}
, sorter = new Toposort()
, sorted
, dep;
options = _.defaults(options || {}, {
reverse: true
});
this.models.forEach(function(model) { return !!model ? model[0] : null;
var deps = [] };
, tableName = model.getTableName();
ModelManager.prototype.__defineGetter__('all', function() {
return this.models;
});
/**
* Iterate over Models in an order suitable for e.g. creating tables. Will
* take foreign key constraints into account so that dependencies are visited
* before dependents.
*/
ModelManager.prototype.forEachModel = function(iterator, options) {
var models = {}
, sorter = new Toposort()
, sorted
, dep;
options = _.defaults(options || {}, {
reverse: true
});
if (_.isObject(tableName)) { this.models.forEach(function(model) {
tableName = tableName.schema + '.' + tableName.tableName; var deps = []
} , tableName = model.getTableName();
models[tableName] = model; if (_.isObject(tableName)) {
tableName = tableName.schema + '.' + tableName.tableName;
}
for (var attrName in model.rawAttributes) { models[tableName] = model;
if (model.rawAttributes.hasOwnProperty(attrName)) {
var attribute = model.rawAttributes[attrName];
if (attribute.references) { for (var attrName in model.rawAttributes) {
attribute = Utils.formatReferences(attribute); if (model.rawAttributes.hasOwnProperty(attrName)) {
dep = attribute.references.model; var attribute = model.rawAttributes[attrName];
if (_.isObject(dep)) { if (attribute.references) {
dep = dep.schema + '.' + dep.tableName; attribute = Utils.formatReferences(attribute);
} dep = attribute.references.model;
deps.push(dep); if (_.isObject(dep)) {
dep = dep.schema + '.' + dep.tableName;
} }
deps.push(dep);
} }
} }
}
deps = deps.filter(function(dep) { deps = deps.filter(function(dep) {
return tableName !== dep; return tableName !== dep;
});
sorter.add(tableName, deps);
}); });
sorted = sorter.sort(); sorter.add(tableName, deps);
if (options.reverse) { });
sorted = sorted.reverse();
} sorted = sorter.sort();
sorted.forEach(function(name) { if (options.reverse) {
iterator(models[name], name); sorted = sorted.reverse();
}); }
}; sorted.forEach(function(name) {
iterator(models[name], name);
});
};
return ModelManager; module.exports = ModelManager;
})();
This diff could not be displayed because it is too large.
'use strict'; 'use strict';
module.exports = (function() { var Attribute = function(options) {
var Attribute = function(options) {
if (options.type === undefined) options = {type: options}; if (options.type === undefined) options = {type: options};
this.type = options.type; this.type = options.type;
}; };
return Attribute; module.exports = Attribute;
})();
...@@ -5,175 +5,173 @@ var Utils = require('./../utils') ...@@ -5,175 +5,173 @@ var Utils = require('./../utils')
, DataTypes = require('../data-types') , DataTypes = require('../data-types')
, Promise = require('bluebird'); , Promise = require('bluebird');
module.exports = (function() { var CounterCache = function(association, options) {
var CounterCache = function(association, options) { this.association = association;
this.association = association; this.source = association.source;
this.source = association.source; this.target = association.target;
this.target = association.target; this.options = options || {};
this.options = options || {};
this.sequelize = this.source.modelManager.sequelize;
this.sequelize = this.source.modelManager.sequelize; this.as = this.options.as;
this.as = this.options.as;
if (association.associationType !== 'HasMany') {
if (association.associationType !== 'HasMany') { throw new Error('Can only have CounterCache on HasMany association');
throw new Error('Can only have CounterCache on HasMany association'); }
}
if (this.as) {
this.isAliased = true;
this.columnName = this.as;
} else {
this.as = 'count_' + this.target.options.name.plural;
this.columnName = Utils._.camelizeIf(
this.as,
!this.source.options.underscored
);
}
this.injectAttributes();
this.injectHooks();
};
// Add countAssociation attribute to source model
CounterCache.prototype.injectAttributes = function() {
// Do not try to use a column that's already taken
Helpers.checkNamingCollision(this);
var newAttributes = {};
newAttributes[this.columnName] = {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: Utils._.partial(
Utils.toDefaultValue,
0
)
};
if (this.as) { Utils.mergeDefaults(this.source.rawAttributes, newAttributes);
this.isAliased = true;
this.columnName = this.as;
} else {
this.as = 'count_' + this.target.options.name.plural;
this.columnName = Utils._.camelizeIf(
this.as,
!this.source.options.underscored
);
}
this.injectAttributes(); // Sync attributes and setters/getters to DAO prototype
this.injectHooks(); this.source.refreshAttributes();
}; };
// Add setAssociaton method to the prototype of the model instance
CounterCache.prototype.injectHooks = function() {
var association = this.association,
counterCacheInstance = this,
CounterUtil,
fullUpdateHook,
atomicHooks,
previousTargetId;
CounterUtil = {
update: function (targetId) {
var query = CounterUtil._targetQuery(targetId);
return association.target.count({ where: query }).then(function (count) {
var newValues = {};
// Add countAssociation attribute to source model query = CounterUtil._sourceQuery(targetId);
CounterCache.prototype.injectAttributes = function() {
// Do not try to use a column that's already taken
Helpers.checkNamingCollision(this);
var newAttributes = {}; newValues[counterCacheInstance.columnName] = count;
newAttributes[this.columnName] = { return association.source.update(newValues, { where: query });
type: DataTypes.INTEGER, });
allowNull: false, },
defaultValue: Utils._.partial( increment: function (targetId) {
Utils.toDefaultValue, var query = CounterUtil._sourceQuery(targetId);
0
)
};
Utils.mergeDefaults(this.source.rawAttributes, newAttributes); return association.source.find({ where: query }).then(function (instance) {
return instance.increment(counterCacheInstance.columnName, { by: 1 });
});
},
decrement: function (targetId) {
var query = CounterUtil._sourceQuery(targetId);
// Sync attributes and setters/getters to DAO prototype return association.source.find({ where: query }).then(function (instance) {
this.source.refreshAttributes(); return instance.decrement(counterCacheInstance.columnName, { by: 1 });
});
},
// helpers
_targetQuery: function (id) {
var query = {};
query[association.identifier] = id;
return query;
},
_sourceQuery: function (id) {
var query = {};
query[association.source.primaryKeyAttribute] = id;
return query;
}
}; };
// Add setAssociaton method to the prototype of the model instance fullUpdateHook = function (target) {
CounterCache.prototype.injectHooks = function() { var targetId = target.get(association.identifier)
var association = this.association, , promises = [];
counterCacheInstance = this,
CounterUtil,
fullUpdateHook,
atomicHooks,
previousTargetId;
CounterUtil = {
update: function (targetId) {
var query = CounterUtil._targetQuery(targetId);
return association.target.count({ where: query }).then(function (count) {
var newValues = {};
query = CounterUtil._sourceQuery(targetId);
newValues[counterCacheInstance.columnName] = count;
return association.source.update(newValues, { where: query });
});
},
increment: function (targetId) {
var query = CounterUtil._sourceQuery(targetId);
return association.source.find({ where: query }).then(function (instance) {
return instance.increment(counterCacheInstance.columnName, { by: 1 });
});
},
decrement: function (targetId) {
var query = CounterUtil._sourceQuery(targetId);
return association.source.find({ where: query }).then(function (instance) {
return instance.decrement(counterCacheInstance.columnName, { by: 1 });
});
},
// helpers
_targetQuery: function (id) {
var query = {};
query[association.identifier] = id;
return query;
},
_sourceQuery: function (id) {
var query = {};
query[association.source.primaryKeyAttribute] = id;
return query;
}
};
fullUpdateHook = function (target) { if (targetId) {
var targetId = target.get(association.identifier) promises.push(CounterUtil.update(targetId));
, promises = []; }
if (previousTargetId && previousTargetId !== targetId) {
promises.push(CounterUtil.update(previousTargetId));
}
return Promise.all(promises).return(undefined);
};
atomicHooks = {
create: function (target) {
var targetId = target.get(association.identifier);
if (targetId) { if (targetId) {
promises.push(CounterUtil.update(targetId)); return CounterUtil.increment(targetId);
} }
},
update: function (target) {
var targetId = target.get(association.identifier)
, promises = [];
if (previousTargetId && previousTargetId !== targetId) { if (targetId && !previousTargetId) {
promises.push(CounterUtil.update(previousTargetId)); promises.push(CounterUtil.increment(targetId));
}
if (!targetId && previousTargetId) {
promises.push(CounterUtil.decrement(targetId));
} }
if (previousTargetId && targetId && previousTargetId !== targetId) {
promises.push(CounterUtil.increment(targetId));
promises.push(CounterUtil.decrement(previousTargetId));
}
return Promise.all(promises);
},
destroy: function (target) {
var targetId = target.get(association.identifier);
return Promise.all(promises).return(undefined); if (targetId) {
}; return CounterUtil.decrement(targetId);
atomicHooks = {
create: function (target) {
var targetId = target.get(association.identifier);
if (targetId) {
return CounterUtil.increment(targetId);
}
},
update: function (target) {
var targetId = target.get(association.identifier)
, promises = [];
if (targetId && !previousTargetId) {
promises.push(CounterUtil.increment(targetId));
}
if (!targetId && previousTargetId) {
promises.push(CounterUtil.decrement(targetId));
}
if (previousTargetId && targetId && previousTargetId !== targetId) {
promises.push(CounterUtil.increment(targetId));
promises.push(CounterUtil.decrement(previousTargetId));
}
return Promise.all(promises);
},
destroy: function (target) {
var targetId = target.get(association.identifier);
if (targetId) {
return CounterUtil.decrement(targetId);
}
} }
};
// previousDataValues are cleared before afterUpdate, so we need to save this here
association.target.addHook('beforeUpdate', function (target) {
previousTargetId = target.previous(association.identifier);
});
if (this.options.atomic === false) {
association.target.addHook('afterCreate', fullUpdateHook);
association.target.addHook('afterUpdate', fullUpdateHook);
association.target.addHook('afterDestroy', fullUpdateHook);
} else {
association.target.addHook('afterCreate', atomicHooks.create);
association.target.addHook('afterUpdate', atomicHooks.update);
association.target.addHook('afterDestroy', atomicHooks.destroy);
} }
}; };
return CounterCache; // previousDataValues are cleared before afterUpdate, so we need to save this here
})(); association.target.addHook('beforeUpdate', function (target) {
previousTargetId = target.previous(association.identifier);
});
if (this.options.atomic === false) {
association.target.addHook('afterCreate', fullUpdateHook);
association.target.addHook('afterUpdate', fullUpdateHook);
association.target.addHook('afterDestroy', fullUpdateHook);
} else {
association.target.addHook('afterCreate', atomicHooks.create);
association.target.addHook('afterUpdate', atomicHooks.update);
association.target.addHook('afterDestroy', atomicHooks.destroy);
}
};
module.exports = CounterCache;
This diff could not be displayed because it is too large.
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
var DataTypes = require('./data-types') var DataTypes = require('./data-types')
, SqlString = require('./sql-string') , SqlString = require('./sql-string')
, lodash = require('lodash') , lodash = require('lodash')
, ParameterValidator = require('./utils/parameter-validator') , parameterValidator = require('./utils/parameter-validator')
, inflection = require('inflection') , inflection = require('inflection')
, dottie = require('dottie') , dottie = require('dottie')
, uuid = require('node-uuid') , uuid = require('node-uuid')
...@@ -398,9 +398,7 @@ var Utils = module.exports = { ...@@ -398,9 +398,7 @@ var Utils = module.exports = {
this.logic = logic; this.logic = logic;
}, },
validateParameter: function(value, expectation, options) { validateParameter: parameterValidator,
return ParameterValidator.check(value, expectation, options);
},
formatReferences: function (obj) { formatReferences: function (obj) {
if (!lodash.isPlainObject(obj.references)) { if (!lodash.isPlainObject(obj.references)) {
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
var _ = require('lodash'); var _ = require('lodash');
var util = require('util'); var util = require('util');
var validateDeprecation = function(value, expectation, options) { function validateDeprecation (value, expectation, options) {
if (!options.deprecated) { if (!options.deprecated) {
return; return;
} }
...@@ -17,9 +17,9 @@ var validateDeprecation = function(value, expectation, options) { ...@@ -17,9 +17,9 @@ var validateDeprecation = function(value, expectation, options) {
} }
return valid; return valid;
}; }
var validate = function(value, expectation) { function validate (value, expectation) {
// the second part of this check is a workaround to deal with an issue that occurs in node-webkit when // the second part of this check is a workaround to deal with an issue that occurs in node-webkit when
// using object literals. https://github.com/sequelize/sequelize/issues/2685 // using object literals. https://github.com/sequelize/sequelize/issues/2685
if (value instanceof expectation || Object.prototype.toString.call(value) === Object.prototype.toString.call(expectation.call())) { if (value instanceof expectation || Object.prototype.toString.call(value) === Object.prototype.toString.call(expectation.call())) {
...@@ -27,31 +27,31 @@ var validate = function(value, expectation) { ...@@ -27,31 +27,31 @@ var validate = function(value, expectation) {
} }
throw new Error(util.format('The parameter (value: %s) is no %s.', value, expectation.name)); throw new Error(util.format('The parameter (value: %s) is no %s.', value, expectation.name));
}; }
module.exports = { function check (value, expectation, options) {
check: function(value, expectation, options) { options = _.extend({
options = _.extend({ deprecated: false,
deprecated: false, index: null,
index: null, method: null,
method: null, optional: false
optional: false }, options || {});
}, options || {});
if (!value && options.optional) {
if (!value && options.optional) { return true;
return true; }
}
if (value === undefined) {
if (value === undefined) { throw new Error('No value has been passed.');
throw new Error('No value has been passed.');
}
if (expectation === undefined) {
throw new Error('No expectation has been passed.');
}
return false
|| validateDeprecation(value, expectation, options)
|| validate(value, expectation, options);
} }
};
if (expectation === undefined) {
throw new Error('No expectation has been passed.');
}
return false
|| validateDeprecation(value, expectation, options)
|| validate(value, expectation, options);
}
module.exports = check;
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!