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

Commit 1ef192b9 by Mick Hansen

refactor(data-types): data types should always be functions, data types should a…

…lways be inited before use
1 parent 8d7c0703
...@@ -249,7 +249,7 @@ module.exports = (function() { ...@@ -249,7 +249,7 @@ module.exports = (function() {
var template = "<%= type %>" var template = "<%= type %>"
, replacements = { type: dataType.type }; , replacements = { type: dataType.type };
if (dataType.type.toString() === DataTypes.ENUM.toString()) { if (dataType.type instanceof DataTypes.ENUM) {
replacements.type = "TEXT"; replacements.type = "TEXT";
if (!(Array.isArray(dataType.values) && (dataType.values.length > 0))) { if (!(Array.isArray(dataType.values) && (dataType.values.length > 0))) {
......
...@@ -368,7 +368,7 @@ InstanceValidator.prototype._validateSchema = function(rawAttribute, field, valu ...@@ -368,7 +368,7 @@ InstanceValidator.prototype._validateSchema = function(rawAttribute, field, valu
this.errors.push(error); this.errors.push(error);
} }
if (rawAttribute.type === DataTypes.STRING || rawAttribute.type instanceof DataTypes.STRING || rawAttribute.type === DataTypes.TEXT) { if (rawAttribute.type === DataTypes.STRING || rawAttribute.type instanceof DataTypes.STRING || rawAttribute.type === DataTypes.TEXT || rawAttribute.type instanceof DataTypes.TEXT) {
if (Array.isArray(value) || (_.isObject(value) && !value._isSequelizeMethod) && !Buffer.isBuffer(value)) { if (Array.isArray(value) || (_.isObject(value) && !value._isSequelizeMethod) && !Buffer.isBuffer(value)) {
error = new sequelizeError.ValidationErrorItem(field + ' cannot be an array or an object', 'string violation', field, value); error = new sequelizeError.ValidationErrorItem(field + ' cannot be an array or an object', 'string violation', field, value);
this.errors.push(error); this.errors.push(error);
......
...@@ -81,22 +81,23 @@ module.exports = (function() { ...@@ -81,22 +81,23 @@ module.exports = (function() {
throw new Error('Unrecognized data type for field ' + name); throw new Error('Unrecognized data type for field ' + name);
} }
if (attribute.type.toString() === DataTypes.ENUM.toString()) { if (typeof attribute.type === "function") attribute.type = new attribute.type();
if (attribute.type instanceof DataTypes.ENUM) {
// The ENUM is a special case where the type is an object containing the values // The ENUM is a special case where the type is an object containing the values
attribute.values = attribute.type.values || attribute.values || []; attribute.values = attribute.values || attribute.type.values || [];
if (!attribute.values.length) { if (!attribute.values.length) {
throw new Error('Values for ENUM haven\'t been defined.'); throw new Error('Values for ENUM haven\'t been defined.');
} }
attributes[name].validate = attributes[name].validate || { attribute.validate = attribute.validate || {
_checkEnum: function(value, next) { _checkEnum: function(value, next) {
var hasValue = value !== undefined var hasValue = value !== undefined
, isMySQL = ['mysql', 'mariadb'].indexOf(options.sequelize.options.dialect) !== -1 , isMySQL = ['mysql', 'mariadb'].indexOf(options.sequelize.options.dialect) !== -1
, ciCollation = !!options.collate && options.collate.match(/_ci$/i) !== null , ciCollation = !!options.collate && options.collate.match(/_ci$/i) !== null
, valueOutOfScope; , valueOutOfScope;
if (isMySQL && ciCollation && hasValue) { if (isMySQL && ciCollation && hasValue) {
var scopeIndex = (attributes[name].values || []).map(function(d) { return d.toLowerCase(); }).indexOf(value.toLowerCase()); var scopeIndex = (attributes[name].values || []).map(function(d) { return d.toLowerCase(); }).indexOf(value.toLowerCase());
valueOutOfScope = scopeIndex === -1; valueOutOfScope = scopeIndex === -1;
...@@ -290,7 +291,7 @@ module.exports = (function() { ...@@ -290,7 +291,7 @@ module.exports = (function() {
this.Instance.prototype.validators = {}; this.Instance.prototype.validators = {};
Utils._.each(this.rawAttributes, function(definition, name) { Utils._.each(this.rawAttributes, function(definition, name) {
var type = definition.type._typeName || definition.type; if (typeof definition.type === "function") definition.type = new definition.type();
definition.Model = self; definition.Model = self;
definition.fieldName = name; definition.fieldName = name;
...@@ -300,21 +301,28 @@ module.exports = (function() { ...@@ -300,21 +301,28 @@ module.exports = (function() {
definition.field = name; definition.field = name;
} }
if (type === DataTypes.BOOLEAN) { if (definition.type instanceof DataTypes.BOOLEAN) {
self._booleanAttributes.push(name); self._booleanAttributes.push(name);
} else if (type === DataTypes.DATE) { } else if (definition.type instanceof DataTypes.DATE) {
self._dateAttributes.push(name); self._dateAttributes.push(name);
} else if (type === DataTypes.HSTORE) { } else if (definition.type instanceof DataTypes.HSTORE) {
self._hstoreAttributes.push(name); self._hstoreAttributes.push(name);
} else if (type === DataTypes.JSON) { } else if (definition.type instanceof DataTypes.JSON) {
self._jsonAttributes.push(name); self._jsonAttributes.push(name);
} else if (type === DataTypes.VIRTUAL) { } else if (definition.type instanceof DataTypes.VIRTUAL) {
self._virtualAttributes.push(name); self._virtualAttributes.push(name);
} }
if (definition.hasOwnProperty('defaultValue')) { if (definition.hasOwnProperty('defaultValue')) {
self._defaultValues[name] = Utils._.partial( if (typeof definition.defaultValue === "function" && (
Utils.toDefaultValue, definition.defaultValue); definition.defaultValue === DataTypes.NOW ||
definition.defaultValue === DataTypes.UUIDV4 ||
definition.defaultValue === DataTypes.UUIDV4
)) {
definition.defaultValue = new definition.defaultValue();
}
self._defaultValues[name] = Utils._.partial(Utils.toDefaultValue, definition.defaultValue);
} }
if (definition.hasOwnProperty('validate')) { if (definition.hasOwnProperty('validate')) {
...@@ -808,12 +816,12 @@ module.exports = (function() { ...@@ -808,12 +816,12 @@ module.exports = (function() {
options.dataType = this.rawAttributes[field].type; options.dataType = this.rawAttributes[field].type;
} else { } else {
// Use FLOAT as fallback // Use FLOAT as fallback
options.dataType = DataTypes.FLOAT; options.dataType = new DataTypes.FLOAT();
} }
} }
options = paranoidClause(this, options); options = paranoidClause(this, options);
return this.QueryInterface.rawSelect(this.getTableName(options), options, aggregateFunction, this); return this.QueryInterface.rawSelect(this.getTableName(options), options, aggregateFunction, this);
}; };
......
...@@ -80,6 +80,27 @@ module.exports = (function() { ...@@ -80,6 +80,27 @@ module.exports = (function() {
attribute = { type: attribute, allowNull: true }; attribute = { type: attribute, allowNull: true };
} }
if (typeof attribute.type === "function") attribute.type = new attribute.type();
if (attribute.hasOwnProperty('defaultValue')) {
if (typeof attribute.defaultValue === "function" && (
attribute.defaultValue === DataTypes.NOW ||
attribute.defaultValue === DataTypes.UUIDV4 ||
attribute.defaultValue === DataTypes.UUIDV4
)) {
attribute.defaultValue = new definition.defaultValue();
}
}
if (attribute.type instanceof DataTypes.ENUM) {
// The ENUM is a special case where the type is an object containing the values
attribute.values = attribute.values || attribute.type.values || [];
if (!attribute.values.length) {
throw new Error('Values for ENUM haven\'t been defined.');
}
}
return attribute; return attribute;
}); });
...@@ -330,8 +351,9 @@ module.exports = (function() { ...@@ -330,8 +351,9 @@ module.exports = (function() {
}); });
}; };
QueryInterface.prototype.addColumn = function(table, key, dataType) { QueryInterface.prototype.addColumn = function(table, key, attribute) {
return this.sequelize.query(this.QueryGenerator.addColumnQuery(table, key, dataType), null, {logging: this.sequelize.options.logging}); if (typeof attribute.type === "function") attribute.type = new attribute.type();
return this.sequelize.query(this.QueryGenerator.addColumnQuery(table, key, attribute), null, {logging: this.sequelize.options.logging});
}; };
QueryInterface.prototype.removeColumn = function(tableName, attributeName) { QueryInterface.prototype.removeColumn = function(tableName, attributeName) {
...@@ -353,6 +375,8 @@ module.exports = (function() { ...@@ -353,6 +375,8 @@ module.exports = (function() {
attributes[attributeName] = dataTypeOrOptions; attributes[attributeName] = dataTypeOrOptions;
} }
if (typeof attributes[attributeName].type === "function") attributes[attributeName].type = new attributes[attributeName].type();
if (this.sequelize.options.dialect === 'sqlite') { if (this.sequelize.options.dialect === 'sqlite') {
// sqlite needs some special treatment as it cannot change a column // sqlite needs some special treatment as it cannot change a column
return SQLiteQueryInterface.changeColumn.call(this, tableName, attributes); return SQLiteQueryInterface.changeColumn.call(this, tableName, attributes);
...@@ -741,13 +765,13 @@ module.exports = (function() { ...@@ -741,13 +765,13 @@ module.exports = (function() {
if (dataType instanceof DataTypes.DECIMAL || dataType instanceof DataTypes.FLOAT) { if (dataType instanceof DataTypes.DECIMAL || dataType instanceof DataTypes.FLOAT) {
result = parseFloat(result); result = parseFloat(result);
} else if (dataType === DataTypes.INTEGER || dataType instanceof DataTypes.BIGINT) { } else if (dataType instanceof DataTypes.INTEGER || dataType instanceof DataTypes.BIGINT) {
result = parseInt(result, 10); result = parseInt(result, 10);
} else if (dataType === DataTypes.DATE) { } else if (dataType instanceof DataTypes.DATE) {
if (!Utils._.isDate(result)) { if (!Utils._.isDate(result)) {
result = new Date(result); result = new Date(result);
} }
} else if (dataType === DataTypes.STRING) { } else if (dataType instanceof DataTypes.STRING) {
// Nothing to do, result is already a string. // Nothing to do, result is already a string.
} }
} }
......
...@@ -473,11 +473,11 @@ var Utils = module.exports = { ...@@ -473,11 +473,11 @@ var Utils = module.exports = {
toDefaultValue: function(value) { toDefaultValue: function(value) {
if (lodash.isFunction(value)) { if (lodash.isFunction(value)) {
return value(); return value();
} else if (value === DataTypes.UUIDV1) { } else if (value instanceof DataTypes.UUIDV1) {
return uuid.v1(); return uuid.v1();
} else if (value === DataTypes.UUIDV4) { } else if (value instanceof DataTypes.UUIDV4) {
return uuid.v4(); return uuid.v4();
} else if (value === DataTypes.NOW) { } else if (value instanceof DataTypes.NOW) {
return Utils.now(); return Utils.now();
} else { } else {
return value; return value;
...@@ -496,9 +496,9 @@ var Utils = module.exports = { ...@@ -496,9 +496,9 @@ var Utils = module.exports = {
// TODO this will be schemable when all supported db // TODO this will be schemable when all supported db
// have been normalized for this case // have been normalized for this case
if (value === DataTypes.NOW) { return false; } if (value instanceof DataTypes.NOW) { return false; }
if (value === DataTypes.UUIDV1 || value === DataTypes.UUIDV4) { return false; } if (value instanceof DataTypes.UUIDV1 || value instanceof DataTypes.UUIDV4) { return false; }
if (lodash.isFunction(value)) { if (lodash.isFunction(value)) {
return false; return false;
......
...@@ -580,7 +580,7 @@ describe(Support.getTestDialectTeaser('BelongsTo'), function() { ...@@ -580,7 +580,7 @@ describe(Support.getTestDialectTeaser('BelongsTo'), function() {
User.belongsTo(Group); User.belongsTo(Group);
self.sequelize.sync({ force: true }).success(function() { self.sequelize.sync({ force: true }).success(function() {
expect(User.rawAttributes.GroupPKBTName.type.toString()).to.equal(DataTypes.STRING.toString()); expect(User.rawAttributes.GroupPKBTName.type.toString()).to.equal(DataTypes.STRING().toString());
done(); done();
}); });
}); });
...@@ -604,7 +604,7 @@ describe(Support.getTestDialectTeaser('BelongsTo'), function() { ...@@ -604,7 +604,7 @@ describe(Support.getTestDialectTeaser('BelongsTo'), function() {
.success(function() { .success(function() {
dataTypes.forEach(function(dataType, i) { dataTypes.forEach(function(dataType, i) {
expect(Tasks[dataType].rawAttributes.userId.type.toString()) expect(Tasks[dataType].rawAttributes.userId.type.toString())
.to.equal(dataType.toString()); .to.equal(dataType().toString());
if ((i + 1) === dataTypes.length) { if ((i + 1) === dataTypes.length) {
done(); done();
......
...@@ -2607,7 +2607,7 @@ describe(Support.getTestDialectTeaser('HasMany'), function() { ...@@ -2607,7 +2607,7 @@ describe(Support.getTestDialectTeaser('HasMany'), function() {
User.hasMany(Tasks[dataType], { foreignKey: 'userId', keyType: dataType, constraints: false }); User.hasMany(Tasks[dataType], { foreignKey: 'userId', keyType: dataType, constraints: false });
return Tasks[dataType].sync({ force: true }).then(function() { return Tasks[dataType].sync({ force: true }).then(function() {
expect(Tasks[dataType].rawAttributes.userId.type.toString()).to.equal(dataType.toString()); expect(Tasks[dataType].rawAttributes.userId.type instanceof dataType).to.be.ok;
}); });
}); });
}); });
...@@ -2624,7 +2624,7 @@ describe(Support.getTestDialectTeaser('HasMany'), function() { ...@@ -2624,7 +2624,7 @@ describe(Support.getTestDialectTeaser('HasMany'), function() {
User.hasMany(Task); User.hasMany(Task);
return this.sequelize.sync({ force: true }).then(function() { return this.sequelize.sync({ force: true }).then(function() {
expect(Task.rawAttributes.UserId.type).to.equal(DataTypes.STRING); expect(Task.rawAttributes.UserId.type instanceof DataTypes.STRING).to.be.ok;
}); });
}); });
......
...@@ -515,7 +515,7 @@ describe(Support.getTestDialectTeaser('HasOne'), function() { ...@@ -515,7 +515,7 @@ describe(Support.getTestDialectTeaser('HasOne'), function() {
Group.hasOne(User); Group.hasOne(User);
self.sequelize.sync({ force: true }).success(function() { self.sequelize.sync({ force: true }).success(function() {
expect(User.rawAttributes.GroupPKBTName.type.toString()).to.equal(Sequelize.STRING.toString()); expect(User.rawAttributes.GroupPKBTName.type.toString()).to.equal(Sequelize.STRING().toString());
done(); done();
}); });
}); });
...@@ -536,7 +536,7 @@ describe(Support.getTestDialectTeaser('HasOne'), function() { ...@@ -536,7 +536,7 @@ describe(Support.getTestDialectTeaser('HasOne'), function() {
Tasks[dataType].sync({ force: true }).success(function() { Tasks[dataType].sync({ force: true }).success(function() {
expect(Tasks[dataType].rawAttributes.userId.type.toString()) expect(Tasks[dataType].rawAttributes.userId.type.toString())
.to.equal(dataType.toString()); .to.equal(dataType().toString());
dataTypes.splice(dataTypes.indexOf(dataType), 1); dataTypes.splice(dataTypes.indexOf(dataType), 1);
if (!dataTypes.length) { if (!dataTypes.length) {
......
...@@ -70,15 +70,16 @@ describe(Support.getTestDialectTeaser('DataTypes'), function() { ...@@ -70,15 +70,16 @@ describe(Support.getTestDialectTeaser('DataTypes'), function() {
[Sequelize.BLOB('tiny'), 'BLOB(\'tiny\')', 'TINYBLOB'], [Sequelize.BLOB('tiny'), 'BLOB(\'tiny\')', 'TINYBLOB'],
[Sequelize.BLOB('medium'), 'BLOB(\'medium\')', 'MEDIUMBLOB'], [Sequelize.BLOB('medium'), 'BLOB(\'medium\')', 'MEDIUMBLOB'],
[Sequelize.BLOB('long'), 'BLOB(\'long\')', 'LONGBLOB'], [Sequelize.BLOB('long'), 'BLOB(\'long\')', 'LONGBLOB'],
[Sequelize.INTEGER, 'INTEGER', 'INTEGER'], [Sequelize.INTEGER, 'INTEGER', 'INTEGER'],
[Sequelize.INTEGER.UNSIGNED, 'INTEGER.UNSIGNED', 'INTEGER UNSIGNED'], [Sequelize.INTEGER.UNSIGNED, 'INTEGER.UNSIGNED', 'INTEGER UNSIGNED'],
[Sequelize.INTEGER.UNSIGNED.ZEROFILL, 'INTEGER.UNSIGNED', 'INTEGER UNSIGNED ZEROFILL'],
[Sequelize.INTEGER(11), 'INTEGER(11)', 'INTEGER(11)'], [Sequelize.INTEGER(11), 'INTEGER(11)', 'INTEGER(11)'],
[Sequelize.INTEGER(11).UNSIGNED, 'INTEGER(11).UNSIGNED', 'INTEGER(11) UNSIGNED'], [Sequelize.INTEGER(11).UNSIGNED, 'INTEGER(11).UNSIGNED', 'INTEGER(11) UNSIGNED'],
[Sequelize.INTEGER(11).UNSIGNED.ZEROFILL, 'INTEGER(11).UNSIGNED.ZEROFILL', 'INTEGER(11) UNSIGNED ZEROFILL'], [Sequelize.INTEGER(11).UNSIGNED.ZEROFILL, 'INTEGER(11).UNSIGNED.ZEROFILL', 'INTEGER(11) UNSIGNED ZEROFILL'],
[Sequelize.INTEGER(11).ZEROFILL, 'INTEGER(11).ZEROFILL', 'INTEGER(11) ZEROFILL'], [Sequelize.INTEGER(11).ZEROFILL, 'INTEGER(11).ZEROFILL', 'INTEGER(11) ZEROFILL'],
[Sequelize.INTEGER(11).ZEROFILL.UNSIGNED, 'INTEGER(11).ZEROFILL.UNSIGNED', 'INTEGER(11) UNSIGNED ZEROFILL'], [Sequelize.INTEGER(11).ZEROFILL.UNSIGNED, 'INTEGER(11).ZEROFILL.UNSIGNED', 'INTEGER(11) UNSIGNED ZEROFILL'],
[Sequelize.BIGINT, 'BIGINT', 'BIGINT'], [Sequelize.BIGINT, 'BIGINT', 'BIGINT'],
[Sequelize.BIGINT.UNSIGNED, 'BIGINT.UNSIGNED', 'BIGINT UNSIGNED'], [Sequelize.BIGINT.UNSIGNED, 'BIGINT.UNSIGNED', 'BIGINT UNSIGNED'],
[Sequelize.BIGINT(11), 'BIGINT(11)', 'BIGINT(11)'], [Sequelize.BIGINT(11), 'BIGINT(11)', 'BIGINT(11)'],
...@@ -124,7 +125,8 @@ describe(Support.getTestDialectTeaser('DataTypes'), function() { ...@@ -124,7 +125,8 @@ describe(Support.getTestDialectTeaser('DataTypes'), function() {
} }
} }
expect(test[0].toString()).to.equal(test[2]); if (typeof test[0] === "function") test[0] = new test[0]();
expect(test[0].toSql()).to.equal(test[2]);
done(); done();
}); });
}); });
......
...@@ -908,8 +908,7 @@ describe(Support.getTestDialectTeaser('Model'), function() { ...@@ -908,8 +908,7 @@ describe(Support.getTestDialectTeaser('Model'), function() {
results.forEach(function(book, index) { results.forEach(function(book, index) {
expect(book.title).to.equal(data.title); expect(book.title).to.equal(data.title);
expect(book.author).to.equal(data.author); expect(book.author).to.equal(data.author);
expect(books[index].rawAttributes.id.type.toString()) expect(books[index].rawAttributes.id.type instanceof dataTypes[index]).to.be.ok;
.to.equal(dataTypes[index].toString());
}); });
done(); done();
}); });
......
...@@ -18,7 +18,7 @@ describe(Support.getTestDialectTeaser('CounterCache'), function() { ...@@ -18,7 +18,7 @@ describe(Support.getTestDialectTeaser('CounterCache'), function() {
User.hasMany(Group, { counterCache: true }); User.hasMany(Group, { counterCache: true });
expect(Object.keys(User.attributes)).to.contain('countGroups'); expect(Object.keys(User.attributes)).to.contain('countGroups');
expect(User.attributes.countGroups.type).to.equal(DataTypes.INTEGER); expect(User.attributes.countGroups.type instanceof DataTypes.INTEGER).to.be.ok;
}); });
it('supports `as`', function() { it('supports `as`', function() {
......
...@@ -834,7 +834,11 @@ describe(Support.getTestDialectTeaser('Sequelize'), function() { ...@@ -834,7 +834,11 @@ describe(Support.getTestDialectTeaser('Sequelize'), function() {
Object.keys(customAttributes).forEach(function(attribute) { Object.keys(customAttributes).forEach(function(attribute) {
Object.keys(customAttributes[attribute]).forEach(function(option) { Object.keys(customAttributes[attribute]).forEach(function(option) {
var optionValue = customAttributes[attribute][option]; var optionValue = customAttributes[attribute][option];
expect(Picture.rawAttributes[attribute][option]).to.be.equal(optionValue); if (typeof optionValue === "function" && optionValue() instanceof DataTypes.ABSTRACT) {
expect(Picture.rawAttributes[attribute][option] instanceof optionValue).to.be.ok;
} else {
expect(Picture.rawAttributes[attribute][option]).to.be.equal(optionValue);
}
}); });
}); });
done(); done();
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!