Skip to content

4.0 Model definition syntax #6524

@felixfbecker

Description

@felixfbecker

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{
        typeDataTypes.STRING,
        primaryKeytrue
    },
    lastNameDataTypes.STRING,
    firstNameDataTypes.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{
                typeDataTypes.STRING,
                primaryKeytrue
            },
            lastNameDataTypes.STRING,
            firstNameDataTypes.STRING,
        }, { sequelize })
    }
}

With the help of a decorator library and Babel transpilation, this is also possible:

@Options({ sequelize })
@Attributes({
    username{
        typeDataTypes.STRING,
        primaryKeytrue
    },
    lastNameDataTypes.STRING,
    firstNameDataTypes.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({
        typeDataTypes.STRING,
        primaryKeytrue
    })
    public usernamestring;
 
    @Attribute(DataTypes.STRING)
    public firstNamestring;
 
    @Attribute() // Type is inferred as DataTypes.STRING 
    public lastNamestring;
 
    get fullName()string {
        return this.firstName + ' ' + this.lastName;
    }
 
    set fullName(fullNamestring) {
        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: #5898 #6439 #5877 #5924 #5205 #4728

Metadata

Metadata

Assignees

No one assigned

    Labels

    status: in discussionFor issues and PRs. Community and maintainers are discussing the applicability of the issue.

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions