Because the dicussion is spread across many issues and PRs, I wanted to open a new issue to discuss the future syntax for model definition.
Currently, besides the old define()
, this syntax is possible in v4.0.0-1:
export class User extends Model {
get fullName() {
return this.firstName + ' ' + this.lastName;
}
set fullName(fullName) {
const names = fullName.split(' ');
this.lastName = names.pop();
this.firstName = names.join(' ');
}
}
User.init(({
username: {
type: DataTypes.STRING,
primaryKey: true
},
lastName: DataTypes.STRING,
firstName: DataTypes.STRING,
}, { sequelize })
If you prefer to not do the initialization (which also attaches the connection to the model) inside the model file, but rather from a model index file, this is also possible:
export class User extends Model {
get fullName() {
return this.firstName + ' ' + this.lastName;
}
set fullName(fullName) {
const names = fullName.split(' ');
this.lastName = names.pop();
this.firstName = names.join(' ');
}
static init(sequelize) {
super.init({
username: {
type: DataTypes.STRING,
primaryKey: true
},
lastName: DataTypes.STRING,
firstName: DataTypes.STRING,
}, { sequelize })
}
}
With the help of a decorator library and Babel transpilation, this is also possible:
@Options({ sequelize })
@Attributes({
username: {
type: DataTypes.STRING,
primaryKey: true
},
lastName: DataTypes.STRING,
firstName: DataTypes.STRING,
})
export class User extends Model {
get fullName() {
return this.firstName + ' ' + this.lastName;
}
set fullName(fullName) {
const names = fullName.split(' ');
this.lastName = names.pop();
this.firstName = names.join(' ');
}
}
And with TypeScript you can go even further:
@Options({ sequelize })
export class User extends Model {
@Attribute({
type: DataTypes.STRING,
primaryKey: true
})
public username: string;
@Attribute(DataTypes.STRING)
public firstName: string;
@Attribute() // Type is inferred as DataTypes.STRING
public lastName: string;
get fullName(): string {
return this.firstName + ' ' + this.lastName;
}
set fullName(fullName: string) {
const names = fullName.split(' ');
this.lastName = names.pop();
this.firstName = names.join(' ');
}
}
BUT we definitely do not want to require the usage of any transpiler. The Model.init()
API feels a bit weird, especially how the sequelize connection is passed. Some thoughts:
- If we want to make models independent one day from connections, this is has the benefit of easily omitting the
sequelize
option
- But we would probably still need to require that models are registered in a model manager, so we could inverse the syntax (something like
sequelize.add(Model)
instead of passing the connection. That is not implemented atm though, currently the model needs to know about the connection.
Please chime in and share your thoughts and ideas!
Issues/PRs for reference: https://github.com/sequelize/sequelize/issues/5898 https://github.com/sequelize/sequelize/pull/6439 https://github.com/sequelize/sequelize/pull/5877 https://github.com/sequelize/sequelize/pull/5924 https://github.com/sequelize/sequelize/issues/5205 https://github.com/sequelize/sequelize/issues/4728
status: in discussion