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

Commit 1eeb343a by Sushant Committed by GitHub

feat(internal): cleanup code base and straightening internal API (#8160)

* autoIncrementField => autoIncrementAttribute

* fieldMap

* this.hasPrimaryKey duplicate removed

* use this.rawAttributes

* remove unused model/attribute file

* dynamically load errors

* parse and properly throw UnknownConstraintError for postgres
1 parent fc2e42ca
...@@ -198,13 +198,13 @@ class AbstractQuery { ...@@ -198,13 +198,13 @@ class AbstractQuery {
handleInsertQuery(results, metaData) { handleInsertQuery(results, metaData) {
if (this.instance) { if (this.instance) {
// add the inserted row id to the instance // add the inserted row id to the instance
const autoIncrementField = this.model.autoIncrementField; const autoIncrementAttribute = this.model.autoIncrementAttribute;
let id = null; let id = null;
id = id || results && results[this.getInsertIdField()]; id = id || results && results[this.getInsertIdField()];
id = id || metaData && metaData[this.getInsertIdField()]; id = id || metaData && metaData[this.getInsertIdField()];
this.instance[autoIncrementField] = id; this.instance[autoIncrementAttribute] = id;
} }
} }
......
...@@ -613,21 +613,6 @@ const QueryGenerator = { ...@@ -613,21 +613,6 @@ const QueryGenerator = {
return result; return result;
}, },
findAutoIncrementField(factory) {
const fields = [];
for (const name in factory.attributes) {
if (factory.attributes.hasOwnProperty(name)) {
const definition = factory.attributes[name];
if (definition && definition.autoIncrement) {
fields.push(name);
}
}
}
return fields;
},
createTrigger() { createTrigger() {
throwMethodUndefined('createTrigger'); throwMethodUndefined('createTrigger');
}, },
......
...@@ -374,20 +374,20 @@ class Query extends AbstractQuery { ...@@ -374,20 +374,20 @@ class Query extends AbstractQuery {
handleInsertQuery(results, metaData) { handleInsertQuery(results, metaData) {
if (this.instance) { if (this.instance) {
// add the inserted row id to the instance // add the inserted row id to the instance
const autoIncrementField = this.model.autoIncrementField; const autoIncrementAttribute = this.model.autoIncrementAttribute;
let id = null; let id = null;
let autoIncrementFieldAlias = null; let autoIncrementAttributeAlias = null;
if (this.model.rawAttributes.hasOwnProperty(autoIncrementField) && if (this.model.rawAttributes.hasOwnProperty(autoIncrementAttribute) &&
this.model.rawAttributes[autoIncrementField].field !== undefined) this.model.rawAttributes[autoIncrementAttribute].field !== undefined)
autoIncrementFieldAlias = this.model.rawAttributes[autoIncrementField].field; autoIncrementAttributeAlias = this.model.rawAttributes[autoIncrementAttribute].field;
id = id || results && results[0][this.getInsertIdField()]; id = id || results && results[0][this.getInsertIdField()];
id = id || metaData && metaData[this.getInsertIdField()]; id = id || metaData && metaData[this.getInsertIdField()];
id = id || results && results[0][autoIncrementField]; id = id || results && results[0][autoIncrementAttribute];
id = id || autoIncrementFieldAlias && results && results[0][autoIncrementFieldAlias]; id = id || autoIncrementAttributeAlias && results && results[0][autoIncrementAttributeAlias];
this.instance[autoIncrementField] = id; this.instance[autoIncrementAttribute] = id;
} }
} }
} }
......
...@@ -295,22 +295,6 @@ const QueryGenerator = { ...@@ -295,22 +295,6 @@ const QueryGenerator = {
return result; return result;
}, },
findAutoIncrementField(factory) {
const fields = [];
for (const name in factory.attributes) {
if (factory.attributes.hasOwnProperty(name)) {
const definition = factory.attributes[name];
if (definition && definition.autoIncrement) {
fields.push(name);
}
}
}
return fields;
},
quoteIdentifier(identifier) { quoteIdentifier(identifier) {
if (identifier === '*') return identifier; if (identifier === '*') return identifier;
return Utils.addTicks(Utils.removeTicks(identifier, '`'), '`'); return Utils.addTicks(Utils.removeTicks(identifier, '`'), '`');
......
...@@ -97,8 +97,8 @@ class Query extends AbstractQuery { ...@@ -97,8 +97,8 @@ class Query extends AbstractQuery {
if ( if (
data.constructor.name === 'ResultSetHeader' data.constructor.name === 'ResultSetHeader'
&& this.model && this.model
&& this.model.autoIncrementField && this.model.autoIncrementAttribute
&& this.model.autoIncrementField === this.model.primaryKeyAttribute && this.model.autoIncrementAttribute === this.model.primaryKeyAttribute
&& this.model.rawAttributes[this.model.primaryKeyAttribute] && this.model.rawAttributes[this.model.primaryKeyAttribute]
) { ) {
const startId = data[this.getInsertIdField()]; const startId = data[this.getInsertIdField()];
......
...@@ -587,20 +587,6 @@ const QueryGenerator = { ...@@ -587,20 +587,6 @@ const QueryGenerator = {
return result; return result;
}, },
findAutoIncrementField(factory) {
const fields = [];
for (const name in factory.attributes) {
const definition = factory.attributes[name];
if (definition && definition.autoIncrement) {
fields.push(name);
}
}
return fields;
},
createTrigger(tableName, triggerName, eventType, fireOnSpec, functionName, functionParams, optionsArray) { createTrigger(tableName, triggerName, eventType, fireOnSpec, functionName, functionParams, optionsArray) {
const decodedEventType = this.decodeTriggerEventType(eventType); const decodedEventType = this.decodeTriggerEventType(eventType);
......
...@@ -179,7 +179,7 @@ class Query extends AbstractQuery { ...@@ -179,7 +179,7 @@ class Query extends AbstractQuery {
// Postgres will treat tables as case-insensitive, so fix the case // Postgres will treat tables as case-insensitive, so fix the case
// of the returned values to match attributes // of the returned values to match attributes
if (this.options.raw === false && this.sequelize.options.quoteIdentifiers === false) { if (this.options.raw === false && this.sequelize.options.quoteIdentifiers === false) {
const attrsMap = _.reduce(this.model.attributes, (m, v, k) => { const attrsMap = _.reduce(this.model.rawAttributes, (m, v, k) => {
m[k.toLowerCase()] = k; m[k.toLowerCase()] = k;
return m; return m;
}, {}); }, {});
...@@ -334,6 +334,19 @@ class Query extends AbstractQuery { ...@@ -334,6 +334,19 @@ class Query extends AbstractQuery {
parent: err parent: err
}); });
case '42704':
if (err.sql && /CONSTRAINT/gi.test(err.sql)) {
message = 'Unknown constraint error';
throw new sequelizeErrors.UnknownConstraintError({
message,
constraint: err.constraint,
fields,
table: err.table,
parent: err
});
}
default: default:
return new sequelizeErrors.DatabaseError(err); return new sequelizeErrors.DatabaseError(err);
} }
......
...@@ -318,21 +318,6 @@ const QueryGenerator = { ...@@ -318,21 +318,6 @@ const QueryGenerator = {
return result; return result;
}, },
findAutoIncrementField(factory) {
const fields = [];
for (const name in factory.attributes) {
if (factory.attributes.hasOwnProperty(name)) {
const definition = factory.attributes[name];
if (definition && definition.autoIncrement) {
fields.push(name);
}
}
}
return fields;
},
showIndexesQuery(tableName) { showIndexesQuery(tableName) {
return `PRAGMA INDEX_LIST(${this.quoteTable(tableName)})`; return `PRAGMA INDEX_LIST(${this.quoteTable(tableName)})`;
}, },
......
...@@ -129,8 +129,8 @@ class Query extends AbstractQuery { ...@@ -129,8 +129,8 @@ class Query extends AbstractQuery {
if ( if (
metaData.constructor.name === 'Statement' metaData.constructor.name === 'Statement'
&& query.model && query.model
&& query.model.autoIncrementField && query.model.autoIncrementAttribute
&& query.model.autoIncrementField === query.model.primaryKeyAttribute && query.model.autoIncrementAttribute === query.model.primaryKeyAttribute
&& query.model.rawAttributes[query.model.primaryKeyAttribute] && query.model.rawAttributes[query.model.primaryKeyAttribute]
) { ) {
const startId = metaData[query.getInsertIdField()] - metaData.changes + 1; const startId = metaData[query.getInsertIdField()] - metaData.changes + 1;
......
...@@ -22,7 +22,7 @@ class InstanceValidator { ...@@ -22,7 +22,7 @@ class InstanceValidator {
options = _.clone(options) || {}; options = _.clone(options) || {};
if (options.fields && !options.skip) { if (options.fields && !options.skip) {
options.skip = Utils._.difference(Object.keys(modelInstance.constructor.attributes), options.fields); options.skip = Utils._.difference(Object.keys(modelInstance.constructor.rawAttributes), options.fields);
} }
// assign defined and default options // assign defined and default options
......
...@@ -38,7 +38,6 @@ const assert = require('assert'); ...@@ -38,7 +38,6 @@ const assert = require('assert');
* @mixes Hooks * @mixes Hooks
*/ */
class Model { class Model {
static get QueryInterface() { static get QueryInterface() {
return this.sequelize.getQueryInterface(); return this.sequelize.getQueryInterface();
} }
...@@ -121,6 +120,7 @@ class Model { ...@@ -121,6 +120,7 @@ class Model {
_autoGenerated: true _autoGenerated: true
}; };
} }
if (this._timestampAttributes.updatedAt) { if (this._timestampAttributes.updatedAt) {
tail[this._timestampAttributes.updatedAt] = { tail[this._timestampAttributes.updatedAt] = {
type: DataTypes.DATE, type: DataTypes.DATE,
...@@ -128,12 +128,14 @@ class Model { ...@@ -128,12 +128,14 @@ class Model {
_autoGenerated: true _autoGenerated: true
}; };
} }
if (this._timestampAttributes.deletedAt) { if (this._timestampAttributes.deletedAt) {
tail[this._timestampAttributes.deletedAt] = { tail[this._timestampAttributes.deletedAt] = {
type: DataTypes.DATE, type: DataTypes.DATE,
_autoGenerated: true _autoGenerated: true
}; };
} }
if (this._versionAttribute) { if (this._versionAttribute) {
tail[this._versionAttribute] = { tail[this._versionAttribute] = {
type: DataTypes.INTEGER, type: DataTypes.INTEGER,
...@@ -165,16 +167,19 @@ class Model { ...@@ -165,16 +167,19 @@ class Model {
} }
} }
static _findAutoIncrementField() { static _findAutoIncrementAttribute() {
const fields = this.QueryGenerator.findAutoIncrementField(this); this.autoIncrementAttribute = null;
this.autoIncrementField = null;
for (const field of fields) { for (const name in this.rawAttributes) {
if (this.autoIncrementField) { if (this.rawAttributes.hasOwnProperty(name)) {
throw new Error('Invalid Instance definition. Only one autoincrement field allowed.'); const definition = this.rawAttributes[name];
} else { if (definition && definition.autoIncrement) {
this.autoIncrementField = field; if (this.autoIncrementAttribute) {
throw new Error('Invalid Instance definition. Only one autoincrement field allowed.');
} else {
this.autoIncrementAttribute = name;
}
}
} }
} }
} }
...@@ -705,6 +710,7 @@ class Model { ...@@ -705,6 +710,7 @@ class Model {
if (!options.sequelize) { if (!options.sequelize) {
throw new Error('No Sequelize instance passed'); throw new Error('No Sequelize instance passed');
} }
this.sequelize = options.sequelize; this.sequelize = options.sequelize;
const globalOptions = this.sequelize.options; const globalOptions = this.sequelize.options;
...@@ -782,18 +788,18 @@ class Model { ...@@ -782,18 +788,18 @@ class Model {
} }
}); });
this.attributes = this.rawAttributes = _.mapValues(attributes, (attribute, name) => { this.rawAttributes = _.mapValues(attributes, (attribute, name) => {
attribute = this.sequelize.normalizeAttribute(attribute); attribute = this.sequelize.normalizeAttribute(attribute);
if (attribute.references && attribute.references.model && attribute.references.model.prototype instanceof Model) {
attribute.references.model = attribute.references.model.tableName;
}
if (attribute.type === undefined) { if (attribute.type === undefined) {
throw new Error('Unrecognized data type for field ' + name); throw new Error('Unrecognized data type for field ' + name);
} }
if (_.get(attribute, 'references.model.prototype') instanceof Model) {
attribute.references.model = attribute.references.model.tableName;
}
return attribute; return attribute;
}); });
...@@ -813,11 +819,7 @@ class Model { ...@@ -813,11 +819,7 @@ class Model {
} }
} }
if (this.options.version) { if (this.options.version) {
if (typeof this.options.version === 'string') { this._versionAttribute = typeof this.options.version === 'string' ? this.options.version : 'version';
this._versionAttribute = this.options.version;
} else {
this._versionAttribute = 'version';
}
} }
// Add head and tail default attributes (id, timestamps) // Add head and tail default attributes (id, timestamps)
...@@ -827,10 +829,10 @@ class Model { ...@@ -827,10 +829,10 @@ class Model {
} }
this._hasReadOnlyAttributes = this._readOnlyAttributes && this._readOnlyAttributes.length; this._hasReadOnlyAttributes = this._readOnlyAttributes && this._readOnlyAttributes.length;
this._isReadOnlyAttribute = Utils._.memoize(key => this._hasReadOnlyAttributes && this._readOnlyAttributes.indexOf(key) !== -1); this._isReadOnlyAttribute = Utils._.memoize(key => this._hasReadOnlyAttributes && this._readOnlyAttributes.indexOf(key) !== -1);
this._addDefaultAttributes(); this._addDefaultAttributes();
this.refreshAttributes(); this.refreshAttributes();
this._findAutoIncrementAttribute();
this._findAutoIncrementField();
this._scope = this.options.defaultScope; this._scope = this.options.defaultScope;
...@@ -845,9 +847,8 @@ class Model { ...@@ -845,9 +847,8 @@ class Model {
}); });
this.options.indexes = this.options.indexes.map(this._conformIndex); this.options.indexes = this.options.indexes.map(this._conformIndex);
this.sequelize.modelManager.addModel(this); this.sequelize.modelManager.addModel(this);
this.sequelize.runHooks('afterDefine', this); this.sequelize.runHooks('afterDefine', this);
return this; return this;
...@@ -1037,7 +1038,10 @@ class Model { ...@@ -1037,7 +1038,10 @@ class Model {
this._hasDefaultValues = !Utils._.isEmpty(this._defaultValues); this._hasDefaultValues = !Utils._.isEmpty(this._defaultValues);
// DEPRECATE: All code base is free from this.attributes now
// This should be removed in v5
this.attributes = this.rawAttributes; this.attributes = this.rawAttributes;
this.tableAttributes = Utils._.omit(this.rawAttributes, this._virtualAttributes); this.tableAttributes = Utils._.omit(this.rawAttributes, this._virtualAttributes);
this.prototype._hasCustomGetters = Object.keys(this.prototype._customGetters).length; this.prototype._hasCustomGetters = Object.keys(this.prototype._customGetters).length;
...@@ -1063,11 +1067,8 @@ class Model { ...@@ -1063,11 +1067,8 @@ class Model {
this.primaryKeyField = this.rawAttributes[this.primaryKeyAttribute].field || this.primaryKeyAttribute; this.primaryKeyField = this.rawAttributes[this.primaryKeyAttribute].field || this.primaryKeyAttribute;
} }
this.primaryKeyCount = this.primaryKeyAttributes.length; this._hasPrimaryKeys = this.primaryKeyAttributes.length > 0;
this._hasPrimaryKeys = this.options.hasPrimaryKeys = this.hasPrimaryKeys = this.primaryKeyCount > 0;
this._isPrimaryKey = Utils._.memoize(key => this.primaryKeyAttributes.indexOf(key) !== -1); this._isPrimaryKey = Utils._.memoize(key => this.primaryKeyAttributes.indexOf(key) !== -1);
} }
/** /**
...@@ -2632,7 +2633,7 @@ class Model { ...@@ -2632,7 +2633,7 @@ class Model {
} }
// We want to skip validations for all other fields // We want to skip validations for all other fields
options.skip = Utils._.difference(Object.keys(this.attributes), Object.keys(values)); options.skip = Utils._.difference(Object.keys(this.rawAttributes), Object.keys(values));
return build.validate(options).then(attributes => { return build.validate(options).then(attributes => {
options.skip = undefined; options.skip = undefined;
if (attributes && attributes.dataValues) { if (attributes && attributes.dataValues) {
...@@ -2958,7 +2959,6 @@ class Model { ...@@ -2958,7 +2959,6 @@ class Model {
this._changed = {}; this._changed = {};
this._modelOptions = this.constructor.options; this._modelOptions = this.constructor.options;
this._options = options || {}; this._options = options || {};
this.hasPrimaryKeys = this.constructor.options.hasPrimaryKeys;
this.__eagerlyLoadedAssociations = []; this.__eagerlyLoadedAssociations = [];
/** /**
* Returns true if this instance has not yet been persisted to the database * Returns true if this instance has not yet been persisted to the database
...@@ -3432,9 +3432,9 @@ class Model { ...@@ -3432,9 +3432,9 @@ class Model {
if (!options.fields) { if (!options.fields) {
if (this.isNewRecord) { if (this.isNewRecord) {
options.fields = Object.keys(this.constructor.attributes); options.fields = Object.keys(this.constructor.rawAttributes);
} else { } else {
options.fields = _.intersection(this.changed(), Object.keys(this.constructor.attributes)); options.fields = _.intersection(this.changed(), Object.keys(this.constructor.rawAttributes));
} }
options.defaultFields = options.fields; options.defaultFields = options.fields;
......
'use strict';
class Attribute {
constructor(options) {
if (options.type === undefined) options = {type: options};
this.type = options.type;
}
}
module.exports = Attribute;
module.exports.Attribute = Attribute;
module.exports.default = Attribute;
...@@ -437,9 +437,9 @@ class Sequelize { ...@@ -437,9 +437,9 @@ class Sequelize {
options.model = options.instance.constructor; options.model = options.instance.constructor;
} }
// Map raw fields to model field names using the `fieldAttributeMap` // map raw fields to model attributes
if (options.model && options.mapToModel && !Utils._.isEmpty(options.model.fieldAttributeMap)) { if (options.mapToModel) {
options.fieldMap = options.model.fieldAttributeMap; options.fieldMap = _.get(options, 'model.fieldAttributeMap', {});
} }
if (typeof sql === 'object') { if (typeof sql === 'object') {
...@@ -1196,59 +1196,16 @@ Sequelize.useInflection = Utils.useInflection; ...@@ -1196,59 +1196,16 @@ Sequelize.useInflection = Utils.useInflection;
Hooks.applyTo(Sequelize); Hooks.applyTo(Sequelize);
Hooks.applyTo(Sequelize.prototype); Hooks.applyTo(Sequelize.prototype);
Sequelize.prototype.Error = Sequelize.Error = /**
sequelizeErrors.BaseError; * Expose various errors available
*/
Sequelize.prototype.ValidationError = Sequelize.ValidationError = for (const error of Object.keys(sequelizeErrors)) {
sequelizeErrors.ValidationError; if (sequelizeErrors[error] === sequelizeErrors.BaseError) {
Sequelize.prototype.Error = Sequelize.Error = sequelizeErrors.BaseError;
Sequelize.prototype.ValidationErrorItem = Sequelize.ValidationErrorItem = } else {
sequelizeErrors.ValidationErrorItem; Sequelize.prototype[error] = Sequelize[error] = sequelizeErrors[error];
}
Sequelize.prototype.OptimisticLockError = Sequelize.OptimisticLockError = }
sequelizeErrors.OptimisticLockError;
Sequelize.prototype.DatabaseError = Sequelize.DatabaseError =
sequelizeErrors.DatabaseError;
Sequelize.prototype.TimeoutError = Sequelize.TimeoutError =
sequelizeErrors.TimeoutError;
Sequelize.prototype.UniqueConstraintError = Sequelize.UniqueConstraintError =
sequelizeErrors.UniqueConstraintError;
Sequelize.prototype.ExclusionConstraintError = Sequelize.ExclusionConstraintError =
sequelizeErrors.ExclusionConstraintError;
Sequelize.prototype.ForeignKeyConstraintError = Sequelize.ForeignKeyConstraintError =
sequelizeErrors.ForeignKeyConstraintError;
Sequelize.prototype.ConnectionError = Sequelize.ConnectionError =
sequelizeErrors.ConnectionError;
Sequelize.prototype.ConnectionRefusedError = Sequelize.ConnectionRefusedError =
sequelizeErrors.ConnectionRefusedError;
Sequelize.prototype.AccessDeniedError = Sequelize.AccessDeniedError =
sequelizeErrors.AccessDeniedError;
Sequelize.prototype.HostNotFoundError = Sequelize.HostNotFoundError =
sequelizeErrors.HostNotFoundError;
Sequelize.prototype.HostNotReachableError = Sequelize.HostNotReachableError =
sequelizeErrors.HostNotReachableError;
Sequelize.prototype.InvalidConnectionError = Sequelize.InvalidConnectionError =
sequelizeErrors.InvalidConnectionError;
Sequelize.prototype.ConnectionTimedOutError = Sequelize.ConnectionTimedOutError =
sequelizeErrors.ConnectionTimedOutError;
Sequelize.prototype.InstanceError = Sequelize.InstanceError =
sequelizeErrors.InstanceError;
Sequelize.prototype.EmptyResultError = Sequelize.EmptyResultError =
sequelizeErrors.EmptyResultError;
module.exports = Sequelize; module.exports = Sequelize;
module.exports.Sequelize = Sequelize; module.exports.Sequelize = Sequelize;
......
...@@ -29,25 +29,25 @@ describe(Support.getTestDialectTeaser('associations'), () => { ...@@ -29,25 +29,25 @@ describe(Support.getTestDialectTeaser('associations'), () => {
const reqValidForeignKey = { foreignKey: { allowNull: false }}; const reqValidForeignKey = { foreignKey: { allowNull: false }};
this.A.belongsTo(this.B, reqValidForeignKey); this.A.belongsTo(this.B, reqValidForeignKey);
this.A.belongsTo(this.C, reqValidForeignKey); this.A.belongsTo(this.C, reqValidForeignKey);
expect(this.A.attributes.CId.type).to.deep.equal(this.C.attributes.id.type); expect(this.A.rawAttributes.CId.type).to.deep.equal(this.C.rawAttributes.id.type);
}); });
it('should not be overwritten for belongsToMany', function() { it('should not be overwritten for belongsToMany', function() {
const reqValidForeignKey = { foreignKey: { allowNull: false }, through: 'ABBridge'}; const reqValidForeignKey = { foreignKey: { allowNull: false }, through: 'ABBridge'};
this.B.belongsToMany(this.A, reqValidForeignKey); this.B.belongsToMany(this.A, reqValidForeignKey);
this.A.belongsTo(this.C, reqValidForeignKey); this.A.belongsTo(this.C, reqValidForeignKey);
expect(this.A.attributes.CId.type).to.deep.equal(this.C.attributes.id.type); expect(this.A.rawAttributes.CId.type).to.deep.equal(this.C.rawAttributes.id.type);
}); });
it('should not be overwritten for hasOne', function() { it('should not be overwritten for hasOne', function() {
const reqValidForeignKey = { foreignKey: { allowNull: false }}; const reqValidForeignKey = { foreignKey: { allowNull: false }};
this.B.hasOne(this.A, reqValidForeignKey); this.B.hasOne(this.A, reqValidForeignKey);
this.A.belongsTo(this.C, reqValidForeignKey); this.A.belongsTo(this.C, reqValidForeignKey);
expect(this.A.attributes.CId.type).to.deep.equal(this.C.attributes.id.type); expect(this.A.rawAttributes.CId.type).to.deep.equal(this.C.rawAttributes.id.type);
}); });
it('should not be overwritten for hasMany', function() { it('should not be overwritten for hasMany', function() {
const reqValidForeignKey = { foreignKey: { allowNull: false }}; const reqValidForeignKey = { foreignKey: { allowNull: false }};
this.B.hasMany(this.A, reqValidForeignKey); this.B.hasMany(this.A, reqValidForeignKey);
this.A.belongsTo(this.C, reqValidForeignKey); this.A.belongsTo(this.C, reqValidForeignKey);
expect(this.A.attributes.CId.type).to.deep.equal(this.C.attributes.id.type); expect(this.A.rawAttributes.CId.type).to.deep.equal(this.C.rawAttributes.id.type);
}); });
}); });
}); });
...@@ -12,10 +12,10 @@ describe(Support.getTestDialectTeaser('hasOne'), () => { ...@@ -12,10 +12,10 @@ describe(Support.getTestDialectTeaser('hasOne'), () => {
Task = current.define('Task', { title: DataTypes.STRING }); Task = current.define('Task', { title: DataTypes.STRING });
User.hasOne(Task); User.hasOne(Task);
expect(Task.attributes.UserId).not.to.be.empty; expect(Task.rawAttributes.UserId).not.to.be.empty;
User.hasOne(Task, {as : 'Shabda'}); User.hasOne(Task, {as : 'Shabda'});
expect(Task.attributes.ShabdaId).not.to.be.empty; expect(Task.rawAttributes.ShabdaId).not.to.be.empty;
}); });
it('should not override custom methods with association mixin', () => { it('should not override custom methods with association mixin', () => {
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!