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

Commit 7f00a55b by Simon Schick Committed by Erik Seliger

docs(define): Update docs to use classes instead of `define` (#10584)

First step in dealing with issues like #10576 
by moving docs towards the more es6-ish and static analysable `Model.init` calls.
1 parent 0b868c83
...@@ -15,13 +15,19 @@ associations available in Sequelize ...@@ -15,13 +15,19 @@ associations available in Sequelize
Let's first begin with a basic concept that you will see used in most associations, **source** and **target** model. Suppose you are trying to add an association between two Models. Here we are adding a `hasOne` association between `User` and `Project`. Let's first begin with a basic concept that you will see used in most associations, **source** and **target** model. Suppose you are trying to add an association between two Models. Here we are adding a `hasOne` association between `User` and `Project`.
```js ```js
const User = sequelize.define('User', { class User extends Model {}
User.init({
name: Sequelize.STRING, name: Sequelize.STRING,
email: Sequelize.STRING email: Sequelize.STRING
}, {
sequelize,
}); });
const Project = sequelize.define('Project', { class Project extends Model {}
Project.init({
name: Sequelize.STRING name: Sequelize.STRING
}, {
sequelize,
}); });
User.hasOne(Project); User.hasOne(Project);
...@@ -34,8 +40,10 @@ User.hasOne(Project); ...@@ -34,8 +40,10 @@ User.hasOne(Project);
When you create associations between your models in sequelize, foreign key references with constraints will automatically be created. The setup below: When you create associations between your models in sequelize, foreign key references with constraints will automatically be created. The setup below:
```js ```js
const Task = sequelize.define('task', { title: Sequelize.STRING }); class Task extends Model {}
const User = sequelize.define('user', { username: Sequelize.STRING }); Task.init({ title: Sequelize.STRING }, { sequelize });
class User extends Model {}
User.init({ username: Sequelize.STRING }, { sequelize });
User.hasMany(Task); // Will add userId to Task model User.hasMany(Task); // Will add userId to Task model
Task.belongsTo(User); // Will also add userId to Task model Task.belongsTo(User); // Will also add userId to Task model
...@@ -77,16 +85,20 @@ foreign keys generated by associations. ...@@ -77,16 +85,20 @@ foreign keys generated by associations.
Let's modify last example to use `underscored` option. Let's modify last example to use `underscored` option.
```js ```js
const Task = sequelize.define('task', { class Task extends Model {}
Task.init({
title: Sequelize.STRING title: Sequelize.STRING
}, { }, {
underscored: true underscored: true,
sequelize,
}); });
const User = sequelize.define('user', { class User extends Model {}
User.init({
username: Sequelize.STRING username: Sequelize.STRING
}, { }, {
underscored: true underscored: true,
sequelize,
}); });
// Will add userId to Task model, but field will be set to `user_id` // Will add userId to Task model, but field will be set to `user_id`
...@@ -128,12 +140,14 @@ With the underscored option attributes injected to model are still camel cased b ...@@ -128,12 +140,14 @@ With the underscored option attributes injected to model are still camel cased b
Adding constraints between tables means that tables must be created in the database in a certain order, when using `sequelize.sync`. If `Task` has a reference to `User`, the `users` table must be created before the `tasks` table can be created. This can sometimes lead to circular references, where sequelize cannot find an order in which to sync. Imagine a scenario of documents and versions. A document can have multiple versions, and for convenience, a document has a reference to its current version. Adding constraints between tables means that tables must be created in the database in a certain order, when using `sequelize.sync`. If `Task` has a reference to `User`, the `users` table must be created before the `tasks` table can be created. This can sometimes lead to circular references, where sequelize cannot find an order in which to sync. Imagine a scenario of documents and versions. A document can have multiple versions, and for convenience, a document has a reference to its current version.
```js ```js
const Document = sequelize.define('document', { class Document extends Model {}
Document.init({
author: Sequelize.STRING author: Sequelize.STRING
}); }, { sequelize });
const Version = sequelize.define('version', { class Version extends Model {}
Version.init({
timestamp: Sequelize.DATE timestamp: Sequelize.DATE
}); }, { sequelize });
Document.hasMany(Version); // This adds documentId attribute to version Document.hasMany(Version); // This adds documentId attribute to version
Document.belongsTo(Version, { Document.belongsTo(Version, {
...@@ -184,14 +198,16 @@ CREATE TABLE IF NOT EXISTS "versions" ( ...@@ -184,14 +198,16 @@ CREATE TABLE IF NOT EXISTS "versions" (
Sometimes you may want to reference another table, without adding any constraints, or associations. In that case you can manually add the reference attributes to your schema definition, and mark the relations between them. Sometimes you may want to reference another table, without adding any constraints, or associations. In that case you can manually add the reference attributes to your schema definition, and mark the relations between them.
```js  ```js 
const Trainer = sequelize.define('trainer', { class Trainer extends Model {}
Trainer.init({
firstName: Sequelize.STRING, firstName: Sequelize.STRING,
lastName: Sequelize.STRING lastName: Sequelize.STRING
}); }, { sequelize });
// Series will have a trainerId = Trainer.id foreign reference key // Series will have a trainerId = Trainer.id foreign reference key
// after we call Trainer.hasMany(series) // after we call Trainer.hasMany(series)
const Series = sequelize.define('series', { class Series extends Model {}
Series.init({
title: Sequelize.STRING, title: Sequelize.STRING,
subTitle: Sequelize.STRING, subTitle: Sequelize.STRING,
description: Sequelize.TEXT, description: Sequelize.TEXT,
...@@ -203,11 +219,12 @@ const Series = sequelize.define('series', { ...@@ -203,11 +219,12 @@ const Series = sequelize.define('series', {
key: 'id' key: 'id'
} }
} }
}); }, { sequelize });
// Video will have seriesId = Series.id foreign reference key // Video will have seriesId = Series.id foreign reference key
// after we call Series.hasOne(Video) // after we call Series.hasOne(Video)
const Video = sequelize.define('video', { class Video extends Model {}
Video.init({
title: Sequelize.STRING, title: Sequelize.STRING,
sequence: Sequelize.INTEGER, sequence: Sequelize.INTEGER,
description: Sequelize.TEXT, description: Sequelize.TEXT,
...@@ -219,7 +236,7 @@ const Video = sequelize.define('video', { ...@@ -219,7 +236,7 @@ const Video = sequelize.define('video', {
key: 'id' key: 'id'
} }
} }
}); }, { sequelize });
Series.hasOne(Video); Series.hasOne(Video);
Trainer.hasMany(Series); Trainer.hasMany(Series);
...@@ -235,8 +252,10 @@ BelongsTo associations are associations where the foreign key for the one-to-one ...@@ -235,8 +252,10 @@ BelongsTo associations are associations where the foreign key for the one-to-one
A simple example would be a **Player** being part of a **Team** with the foreign key on the player. A simple example would be a **Player** being part of a **Team** with the foreign key on the player.
```js ```js
const Player = this.sequelize.define('player', {/* attributes */}); class Player extends Model {}
const Team = this.sequelize.define('team', {/* attributes */}); Player.init({/* attributes */}, { sequelize });
class Team extends Model {}
Team.init({/* attributes */}, { sequelize });
Player.belongsTo(Team); // Will add a teamId attribute to Player to hold the primary key value for Team Player.belongsTo(Team); // Will add a teamId attribute to Player to hold the primary key value for Team
``` ```
...@@ -248,19 +267,23 @@ By default the foreign key for a belongsTo relation will be generated from the t ...@@ -248,19 +267,23 @@ By default the foreign key for a belongsTo relation will be generated from the t
The default casing is `camelCase`. If the source model is configured with `underscored: true` the foreignKey will be created with field `snake_case`. The default casing is `camelCase`. If the source model is configured with `underscored: true` the foreignKey will be created with field `snake_case`.
```js ```js
const User = this.sequelize.define('user', {/* attributes */}) class User extends Model {}
const Company = this.sequelize.define('company', {/* attributes */}); User.init({/* attributes */}, { sequelize })
class Company extends Model {}
Company.init({/* attributes */}, { sequelize });
// will add companyId to user // will add companyId to user
User.belongsTo(Company); User.belongsTo(Company);
const User = this.sequelize.define('user', {/* attributes */}, {underscored: true}) class User extends Model {}
const Company = this.sequelize.define('company', { User.init({/* attributes */}, {underscored: true, sequelize})
class Company extends Model {}
Company.init({
uuid: { uuid: {
type: Sequelize.UUID, type: Sequelize.UUID,
primaryKey: true primaryKey: true
} }
}); }, { sequelize });
// will add companyUuid to user with field company_uuid // will add companyUuid to user with field company_uuid
User.belongsTo(Company); User.belongsTo(Company);
...@@ -269,8 +292,10 @@ User.belongsTo(Company); ...@@ -269,8 +292,10 @@ User.belongsTo(Company);
In cases where `as` has been defined it will be used in place of the target model name. In cases where `as` has been defined it will be used in place of the target model name.
```js ```js
const User = this.sequelize.define('user', {/* attributes */}) class User extends Model {}
const UserRole = this.sequelize.define('userRole', {/* attributes */}); User.init({/* attributes */}, { sequelize })
class UserRole extends Model {}
UserRole.init({/* attributes */}, { sequelize });
User.belongsTo(UserRole, {as: 'role'}); // Adds roleId to user rather than userRoleId User.belongsTo(UserRole, {as: 'role'}); // Adds roleId to user rather than userRoleId
``` ```
...@@ -279,8 +304,10 @@ In all cases the default foreign key can be overwritten with the `foreignKey` op ...@@ -279,8 +304,10 @@ In all cases the default foreign key can be overwritten with the `foreignKey` op
When the foreign key option is used, Sequelize will use it as-is: When the foreign key option is used, Sequelize will use it as-is:
```js ```js
const User = this.sequelize.define('user', {/* attributes */}) class User extends Model {}
const Company = this.sequelize.define('company', {/* attributes */}); User.init({/* attributes */}, { sequelize })
class Company extends Model {}
Company.init({/* attributes */}, { sequelize });
User.belongsTo(Company, {foreignKey: 'fk_company'}); // Adds fk_company to User User.belongsTo(Company, {foreignKey: 'fk_company'}); // Adds fk_company to User
``` ```
...@@ -290,8 +317,10 @@ User.belongsTo(Company, {foreignKey: 'fk_company'}); // Adds fk_company to User ...@@ -290,8 +317,10 @@ User.belongsTo(Company, {foreignKey: 'fk_company'}); // Adds fk_company to User
The target key is the column on the target model that the foreign key column on the source model points to. By default the target key for a belongsTo relation will be the target model's primary key. To define a custom column, use the `targetKey` option. The target key is the column on the target model that the foreign key column on the source model points to. By default the target key for a belongsTo relation will be the target model's primary key. To define a custom column, use the `targetKey` option.
```js ```js
const User = this.sequelize.define('user', {/* attributes */}) class User extends Model {}
const Company = this.sequelize.define('company', {/* attributes */}); User.init({/* attributes */}, { sequelize })
class Company extends Model {}
Company.init({/* attributes */}, { sequelize });
User.belongsTo(Company, {foreignKey: 'fk_companyname', targetKey: 'name'}); // Adds fk_companyname to User User.belongsTo(Company, {foreignKey: 'fk_companyname', targetKey: 'name'}); // Adds fk_companyname to User
``` ```
...@@ -301,8 +330,10 @@ User.belongsTo(Company, {foreignKey: 'fk_companyname', targetKey: 'name'}); // A ...@@ -301,8 +330,10 @@ User.belongsTo(Company, {foreignKey: 'fk_companyname', targetKey: 'name'}); // A
HasOne associations are associations where the foreign key for the one-to-one relation exists on the **target model**. HasOne associations are associations where the foreign key for the one-to-one relation exists on the **target model**.
```js ```js
const User = sequelize.define('user', {/* ... */}) class User extends Model {}
const Project = sequelize.define('project', {/* ... */}) User.init({/* ... */}, { sequelize })
class Project extends Model {}
Project.init({/* ... */}, { sequelize })
   
// One-way associations // One-way associations
Project.hasOne(User) Project.hasOne(User)
...@@ -330,7 +361,8 @@ Project.hasOne(User, { as: 'Initiator' }) ...@@ -330,7 +361,8 @@ Project.hasOne(User, { as: 'Initiator' })
// Now you will get Project.getInitiator and Project.setInitiator // Now you will get Project.getInitiator and Project.setInitiator
   
// Or let's define some self references // Or let's define some self references
const Person = sequelize.define('person', { /* ... */}) class Person extends Model {}
Person.init({ /* ... */}, { sequelize })
   
Person.hasOne(Person, {as: 'Father'}) Person.hasOne(Person, {as: 'Father'})
// this will add the attribute FatherId to Person // this will add the attribute FatherId to Person
...@@ -357,8 +389,10 @@ Even though it is called a HasOne association, for most 1:1 relations you usuall ...@@ -357,8 +389,10 @@ Even though it is called a HasOne association, for most 1:1 relations you usuall
The source key is the attribute on the source model that the foreign key attribute on the target model points to. By default the source key for a `hasOne` relation will be the source model's primary attribute. To use a custom attribute, use the `sourceKey` option. The source key is the attribute on the source model that the foreign key attribute on the target model points to. By default the source key for a `hasOne` relation will be the source model's primary attribute. To use a custom attribute, use the `sourceKey` option.
```js ```js
const User = this.sequelize.define('user', {/* attributes */}) class User extends Model {}
const Company = this.sequelize.define('company', {/* attributes */}); User.init({/* attributes */}, { sequelize })
class Company extends Model {}
Company.init({/* attributes */}, { sequelize });
// Adds companyName attribute to User // Adds companyName attribute to User
// Use name attribute from Company as source attribute // Use name attribute from Company as source attribute
...@@ -372,8 +406,10 @@ In Sequelize 1:1 relationship can be set using HasOne and BelongsTo. They are su ...@@ -372,8 +406,10 @@ In Sequelize 1:1 relationship can be set using HasOne and BelongsTo. They are su
Suppose we have two tables to link **Player** and **Team**. Lets define their models. Suppose we have two tables to link **Player** and **Team**. Lets define their models.
```js ```js
const Player = this.sequelize.define('player', {/* attributes */}) class Player extends Model {}
const Team = this.sequelize.define('team', {/* attributes */}); Player.init({/* attributes */}, { sequelize })
class Team extends Model {}
Team.init({/* attributes */}, { sequelize });
``` ```
When we link two models in Sequelize we can refer them as pairs of **source** and **target** models. Like this When we link two models in Sequelize we can refer them as pairs of **source** and **target** models. Like this
...@@ -397,9 +433,12 @@ HasOne and BelongsTo insert the association key in different models from each ot ...@@ -397,9 +433,12 @@ HasOne and BelongsTo insert the association key in different models from each ot
Here is an example demonstrating use cases of BelongsTo and HasOne. Here is an example demonstrating use cases of BelongsTo and HasOne.
```js ```js
const Player = this.sequelize.define('player', {/* attributes */}) class Player extends Model {}
const Coach = this.sequelize.define('coach', {/* attributes */}) Player.init({/* attributes */}, { sequelize })
const Team = this.sequelize.define('team', {/* attributes */}); class Coach extends Model {}
Coach.init({/* attributes */}, { sequelize })
class Team extends Model {}
Team.init({/* attributes */}, { sequelize });
``` ```
Suppose our `Player` model has information about its team as `teamId` column. Information about each Team's `Coach` is stored in the `Team` model as `coachId` column. These both scenarios requires different kind of 1:1 relation because foreign key relation is present on different models each time. Suppose our `Player` model has information about its team as `teamId` column. Information about each Team's `Coach` is stored in the `Team` model as `coachId` column. These both scenarios requires different kind of 1:1 relation because foreign key relation is present on different models each time.
...@@ -420,8 +459,10 @@ Coach.hasOne(Team) // `coachId` will be added on Team / Target model ...@@ -420,8 +459,10 @@ Coach.hasOne(Team) // `coachId` will be added on Team / Target model
One-To-Many associations are connecting one source with multiple targets. The targets however are again connected to exactly one specific source. One-To-Many associations are connecting one source with multiple targets. The targets however are again connected to exactly one specific source.
```js ```js
const User = sequelize.define('user', {/* ... */}) class User extends Model {}
const Project = sequelize.define('project', {/* ... */}) User.init({/* ... */}, { sequelize })
class Project extends Model {}
Project.init({/* ... */}, { sequelize })
   
// OK. Now things get more complicated (not really visible to the user :)). // OK. Now things get more complicated (not really visible to the user :)).
// First let's define a hasMany association // First let's define a hasMany association
...@@ -433,8 +474,10 @@ This will add the attribute `projectId` to User. Depending on your setting for u ...@@ -433,8 +474,10 @@ This will add the attribute `projectId` to User. Depending on your setting for u
Sometimes you may need to associate records on different columns, you may use `sourceKey` option: Sometimes you may need to associate records on different columns, you may use `sourceKey` option:
```js ```js
const City = sequelize.define('city', { countryCode: Sequelize.STRING }); class City extends Model {}
const Country = sequelize.define('country', { isoCode: Sequelize.STRING }); City.init({ countryCode: Sequelize.STRING }, { sequelize });
class Country extends Model {}
Country.init({ isoCode: Sequelize.STRING }, { sequelize });
// Here we can connect countries and cities base on country code // Here we can connect countries and cities base on country code
Country.hasMany(City, {foreignKey: 'countryCode', sourceKey: 'isoCode'}); Country.hasMany(City, {foreignKey: 'countryCode', sourceKey: 'isoCode'});
...@@ -481,11 +524,14 @@ Person.belongsToMany(Person, { as: 'Children', through: 'PersonChildren' }) ...@@ -481,11 +524,14 @@ Person.belongsToMany(Person, { as: 'Children', through: 'PersonChildren' })
If you want additional attributes in your join table, you can define a model for the join table in sequelize, before you define the association, and then tell sequelize that it should use that model for joining, instead of creating a new one: If you want additional attributes in your join table, you can define a model for the join table in sequelize, before you define the association, and then tell sequelize that it should use that model for joining, instead of creating a new one:
```js ```js
const User = sequelize.define('user', {}) class User extends Model {}
const Project = sequelize.define('project', {}) User.init({}, { sequelize })
const UserProjects = sequelize.define('userProjects', { class Project extends Model {}
status: DataTypes.STRING Project.init({}, { sequelize })
}) class UserProjects extends Model {}
UserProjects.init({
status: DataTypes.STRING
}, { sequelize })
   
User.belongsToMany(Project, { through: UserProjects }) User.belongsToMany(Project, { through: UserProjects })
Project.belongsToMany(User, { through: UserProjects }) Project.belongsToMany(User, { through: UserProjects })
...@@ -500,14 +546,15 @@ user.addProject(project, { through: { status: 'started' }}) ...@@ -500,14 +546,15 @@ user.addProject(project, { through: { status: 'started' }})
By default the code above will add projectId and userId to the UserProjects table, and _remove any previously defined primary key attribute_ - the table will be uniquely identified by the combination of the keys of the two tables, and there is no reason to have other PK columns. To enforce a primary key on the `UserProjects` model you can add it manually. By default the code above will add projectId and userId to the UserProjects table, and _remove any previously defined primary key attribute_ - the table will be uniquely identified by the combination of the keys of the two tables, and there is no reason to have other PK columns. To enforce a primary key on the `UserProjects` model you can add it manually.
```js ```js
const UserProjects = sequelize.define('userProjects', { class UserProjects extends Model {}
UserProjects.init({
id: { id: {
type: Sequelize.INTEGER, type: Sequelize.INTEGER,
primaryKey: true, primaryKey: true,
autoIncrement: true autoIncrement: true
}, },
status: DataTypes.STRING status: DataTypes.STRING
}) }, { sequelize })
``` ```
With Belongs-To-Many you can query based on **through** relation and select specific attributes. For example using `findAll` with **through** With Belongs-To-Many you can query based on **through** relation and select specific attributes. For example using `findAll` with **through**
...@@ -542,11 +589,13 @@ User.belongsToMany(Project, { as: { singular: 'task', plural: 'tasks' }}) ...@@ -542,11 +589,13 @@ User.belongsToMany(Project, { as: { singular: 'task', plural: 'tasks' }})
If you know that a model will always use the same alias in associations, you can provide it when creating the model If you know that a model will always use the same alias in associations, you can provide it when creating the model
```js ```js
const Project = sequelize.define('project', attributes, { class Project extends Model {}
Project.init(attributes, {
name: { name: {
singular: 'task', singular: 'task',
plural: 'tasks', plural: 'tasks',
} },
sequelize,
}) })
   
User.belongsToMany(Project); User.belongsToMany(Project);
...@@ -727,21 +776,24 @@ Association scopes allow you to place a scope (a set of default attributes for ` ...@@ -727,21 +776,24 @@ Association scopes allow you to place a scope (a set of default attributes for `
Assume we have models Comment, Post, and Image. A comment can be associated to either an image or a post via `commentableId` and `commentable` - we say that Post and Image are `Commentable` Assume we have models Comment, Post, and Image. A comment can be associated to either an image or a post via `commentableId` and `commentable` - we say that Post and Image are `Commentable`
```js ```js
const Post = sequelize.define('post', { class Post extends Model {}
Post.init({
title: Sequelize.STRING, title: Sequelize.STRING,
text: Sequelize.STRING text: Sequelize.STRING
}); }, { sequelize });
const Image = sequelize.define('image', { class Image extends Model {}
Image.init({
title: Sequelize.STRING, title: Sequelize.STRING,
link: Sequelize.STRING link: Sequelize.STRING
}); }, { sequelize });
const Comment = sequelize.define('comment', { class Comment extends Model {}
Comment.init({
title: Sequelize.STRING, title: Sequelize.STRING,
commentable: Sequelize.STRING, commentable: Sequelize.STRING,
commentableId: Sequelize.INTEGER commentableId: Sequelize.INTEGER
}); }, { sequelize });
Comment.prototype.getItem = function(options) { Comment.prototype.getItem = function(options) {
return this[ return this[
...@@ -811,7 +863,8 @@ Continuing with the idea of a polymorphic model, consider a tag table - an item ...@@ -811,7 +863,8 @@ Continuing with the idea of a polymorphic model, consider a tag table - an item
For brevity, the example only shows a Post model, but in reality Tag would be related to several other models. For brevity, the example only shows a Post model, but in reality Tag would be related to several other models.
```js ```js
const ItemTag = sequelize.define('item_tag', { class ItemTag extends Model {}
ItemTag.init({
id: { id: {
type: Sequelize.INTEGER, type: Sequelize.INTEGER,
primaryKey: true, primaryKey: true,
...@@ -830,12 +883,13 @@ const ItemTag = sequelize.define('item_tag', { ...@@ -830,12 +883,13 @@ const ItemTag = sequelize.define('item_tag', {
unique: 'item_tag_taggable', unique: 'item_tag_taggable',
references: null references: null
} }
}); }, { sequelize });
const Tag = sequelize.define('tag', { class Tag extends Model {}
Tag.init({
name: Sequelize.STRING, name: Sequelize.STRING,
status: Sequelize.STRING status: Sequelize.STRING
}); }, { sequelize });
Post.belongsToMany(Tag, { Post.belongsToMany(Tag, {
through: { through: {
...@@ -915,21 +969,24 @@ An instance can be created with nested association in one step, provided all ele ...@@ -915,21 +969,24 @@ An instance can be created with nested association in one step, provided all ele
Consider the following models: Consider the following models:
```js ```js
const Product = this.sequelize.define('product', { class Product extends Model {}
Product.init({
title: Sequelize.STRING title: Sequelize.STRING
}); }, { sequelize });
const User = this.sequelize.define('user', { class User extends Model {}
User.init({
firstName: Sequelize.STRING, firstName: Sequelize.STRING,
lastName: Sequelize.STRING lastName: Sequelize.STRING
}); }, { sequelize });
const Address = this.sequelize.define('address', { class Address extends Model {}
Address.init({
type: Sequelize.STRING, type: Sequelize.STRING,
line1: Sequelize.STRING, line1: Sequelize.STRING,
line2: Sequelize.STRING, line2: Sequelize.STRING,
city: Sequelize.STRING, city: Sequelize.STRING,
state: Sequelize.STRING, state: Sequelize.STRING,
zip: Sequelize.STRING, zip: Sequelize.STRING,
}); }, { sequelize });
Product.User = Product.belongsTo(User); Product.User = Product.belongsTo(User);
User.Addresses = User.hasMany(Address); User.Addresses = User.hasMany(Address);
...@@ -985,9 +1042,10 @@ return Product.create({ ...@@ -985,9 +1042,10 @@ return Product.create({
Let's introduce the ability to associate a product with many tags. Setting up the models could look like: Let's introduce the ability to associate a product with many tags. Setting up the models could look like:
```js ```js
const Tag = this.sequelize.define('tag', { class Tag extends Model {}
Tag.init({
name: Sequelize.STRING name: Sequelize.STRING
}); }, { sequelize });
Product.hasMany(Tag); Product.hasMany(Tag);
// Also works for `belongsToMany`. // Also works for `belongsToMany`.
......
...@@ -91,12 +91,13 @@ Usage in object notation: ...@@ -91,12 +91,13 @@ Usage in object notation:
```js ```js
// for enums: // for enums:
sequelize.define('model', { class MyModel extends Model {}
MyModel.init({
states: { states: {
type: Sequelize.ENUM, type: Sequelize.ENUM,
values: ['active', 'pending', 'deleted'] values: ['active', 'pending', 'deleted']
} }
}) }, { sequelize })
``` ```
### Array(ENUM) ### Array(ENUM)
......
...@@ -90,10 +90,33 @@ Sequelize will keep the connection open by default, and use the same connection ...@@ -90,10 +90,33 @@ Sequelize will keep the connection open by default, and use the same connection
## Modeling a table ## Modeling a table
Models are defined with `sequelize.define('name', attributes, options)`:
Models are defined with `Model.init(attributes, options)`:
```js
class User extends Model {}
User.init({
// attributes
firstName: {
type: Sequelize.STRING,
allowNull: false
},
lastName: {
type: Sequelize.STRING
// allowNull defaults to true
}
}, {
sequelize,
// options
});
```
Alternatively (legacy):
```js ```js
const User = sequelize.define('user', { const User = sequelize.define('User', {
// attributes
firstName: { firstName: {
type: Sequelize.STRING, type: Sequelize.STRING,
allowNull: false allowNull: false
...@@ -102,6 +125,8 @@ const User = sequelize.define('user', { ...@@ -102,6 +125,8 @@ const User = sequelize.define('user', {
type: Sequelize.STRING type: Sequelize.STRING
// allowNull defaults to true // allowNull defaults to true
} }
}, {
// options
}); });
``` ```
...@@ -123,10 +148,12 @@ const sequelize = new Sequelize(connectionURI, { ...@@ -123,10 +148,12 @@ const sequelize = new Sequelize(connectionURI, {
}); });
// Here `timestamps` will be false, so the `createdAt` and `updatedAt` fields will not be created. // Here `timestamps` will be false, so the `createdAt` and `updatedAt` fields will not be created.
const Foo = sequelize.define('foo', { /* ... */ }); class Foo extends Model {}
Foo.init({ /* ... */ }, { sequelize });
// Here `timestamps` is directly set to true, so the `createdAt` and `updatedAt` fields will be created. // Here `timestamps` is directly set to true, so the `createdAt` and `updatedAt` fields will be created.
const Bar = sequelize.define('bar', { /* ... */ }, { timestamps: true }); class Bar extends Model {}
Bar.init({ /* ... */ }, { sequelize, timestamps: true });
``` ```
You can read more about creating models in the [define API Reference](/class/lib/sequelize.js~Sequelize.html#instance-method-define) and the [Model API reference](/class/lib/model.js~Model.html). You can read more about creating models in the [define API Reference](/class/lib/sequelize.js~Sequelize.html#instance-method-define) and the [Model API reference](/class/lib/model.js~Model.html).
......
...@@ -47,8 +47,9 @@ Arguments to hooks are passed by reference. This means, that you can change the ...@@ -47,8 +47,9 @@ Arguments to hooks are passed by reference. This means, that you can change the
There are currently three ways to programmatically add hooks: There are currently three ways to programmatically add hooks:
```js ```js
// Method 1 via the .define() method // Method 1 via the .init() method
const User = sequelize.define('user', { class User extends Model {}
User.init({
username: DataTypes.STRING, username: DataTypes.STRING,
mood: { mood: {
type: DataTypes.ENUM, type: DataTypes.ENUM,
...@@ -62,7 +63,8 @@ const User = sequelize.define('user', { ...@@ -62,7 +63,8 @@ const User = sequelize.define('user', {
afterValidate: (user, options) => { afterValidate: (user, options) => {
user.username = 'Toni'; user.username = 'Toni';
} }
} },
sequelize
}); });
// Method 2 via the .addHook() method // Method 2 via the .addHook() method
...@@ -91,9 +93,10 @@ User.afterValidate('myHookAfter', (user, options) => { ...@@ -91,9 +93,10 @@ User.afterValidate('myHookAfter', (user, options) => {
Only a hook with name param can be removed. Only a hook with name param can be removed.
```js ```js
const Book = sequelize.define('book', { class Book extends Model {}
Book.init({
title: DataTypes.STRING title: DataTypes.STRING
}); }, { sequelize });
Book.addHook('afterCreate', 'notifyUsers', (book, options) => { Book.addHook('afterCreate', 'notifyUsers', (book, options) => {
// ... // ...
...@@ -123,13 +126,16 @@ const sequelize = new Sequelize(..., { ...@@ -123,13 +126,16 @@ const sequelize = new Sequelize(..., {
This adds a default hook to all models, which is run if the model does not define its own `beforeCreate` hook: This adds a default hook to all models, which is run if the model does not define its own `beforeCreate` hook:
```js ```js
const User = sequelize.define('user'); class User extends Model {}
const Project = sequelize.define('project', {}, { User.init({}, { sequelize });
class Project extends Model {}
Project.init({}, {
hooks: { hooks: {
beforeCreate: () => { beforeCreate: () => {
// Do other stuff // Do other stuff
} }
} },
sequelize
}); });
User.create() // Runs the global hook User.create() // Runs the global hook
...@@ -146,13 +152,16 @@ sequelize.addHook('beforeCreate', () => { ...@@ -146,13 +152,16 @@ sequelize.addHook('beforeCreate', () => {
This hook is always run before create, regardless of whether the model specifies its own `beforeCreate` hook. Local hooks are always run before global hooks: This hook is always run before create, regardless of whether the model specifies its own `beforeCreate` hook. Local hooks are always run before global hooks:
```js ```js
const User = sequelize.define('user'); class User extends Model {}
const Project = sequelize.define('project', {}, { User.init({}, { sequelize });
class Project extends Model {}
Project.init({}, {
hooks: { hooks: {
beforeCreate: () => { beforeCreate: () => {
// Do other stuff // Do other stuff
} }
} },
sequelize
}); });
User.create() // Runs the global hook User.create() // Runs the global hook
...@@ -318,13 +327,15 @@ For the most part hooks will work the same for instances when being associated e ...@@ -318,13 +327,15 @@ For the most part hooks will work the same for instances when being associated e
2. The only way to call beforeDestroy/afterDestroy hooks are on associations with `onDelete: 'cascade'` and the option `hooks: true`. For instance: 2. The only way to call beforeDestroy/afterDestroy hooks are on associations with `onDelete: 'cascade'` and the option `hooks: true`. For instance:
```js ```js
const Projects = sequelize.define('projects', { class Projects extends Model {}
Projects.init({
title: DataTypes.STRING title: DataTypes.STRING
}); }, { sequelize });
const Tasks = sequelize.define('tasks', { class Tasks extends Model {}
Tasks.init({
title: DataTypes.STRING title: DataTypes.STRING
}); }, { sequelize });
Projects.hasMany(Tasks, { onDelete: 'cascade', hooks: true }); Projects.hasMany(Tasks, { onDelete: 'cascade', hooks: true });
Tasks.belongsTo(Projects); Tasks.belongsTo(Projects);
......
...@@ -33,10 +33,11 @@ You are currently looking at the **Tutorials and Guides** for Sequelize. You mig ...@@ -33,10 +33,11 @@ You are currently looking at the **Tutorials and Guides** for Sequelize. You mig
const Sequelize = require('sequelize'); const Sequelize = require('sequelize');
const sequelize = new Sequelize('postgres://user:pass@example.com:5432/dbname'); const sequelize = new Sequelize('postgres://user:pass@example.com:5432/dbname');
const User = sequelize.define('user', { class User extends Model {}
User.init({
username: Sequelize.STRING, username: Sequelize.STRING,
birthday: Sequelize.DATE birthday: Sequelize.DATE
}); }, { sequelize });
sequelize.sync() sequelize.sync()
.then(() => User.create({ .then(() => User.create({
......
...@@ -21,10 +21,11 @@ Built instances will automatically get default values when they were defined&col ...@@ -21,10 +21,11 @@ Built instances will automatically get default values when they were defined&col
```js ```js
// first define the model // first define the model
const Task = sequelize.define('task', { class Task extends Model {}
Task.init({
title: Sequelize.STRING, title: Sequelize.STRING,
rating: { type: Sequelize.TINYINT, defaultValue: 3 } rating: { type: Sequelize.TINYINT, defaultValue: 3 }
}) }, { sequelize });
   
// now instantiate an object // now instantiate an object
const task = Task.build({title: 'very important task'}) const task = Task.build({title: 'very important task'})
...@@ -227,7 +228,8 @@ User.bulkCreate([ ...@@ -227,7 +228,8 @@ User.bulkCreate([
`bulkCreate` was originally made to be a mainstream/fast way of inserting records, however, sometimes you want the luxury of being able to insert multiple rows at once without sacrificing model validations even when you explicitly tell Sequelize which columns to sift through. You can do by adding a `validate: true` property to the options object. `bulkCreate` was originally made to be a mainstream/fast way of inserting records, however, sometimes you want the luxury of being able to insert multiple rows at once without sacrificing model validations even when you explicitly tell Sequelize which columns to sift through. You can do by adding a `validate: true` property to the options object.
```js ```js
const Tasks = sequelize.define('task', { class Tasks extends Model {}
Tasks.init({
name: { name: {
type: Sequelize.STRING, type: Sequelize.STRING,
validate: { validate: {
...@@ -240,7 +242,7 @@ const Tasks = sequelize.define('task', { ...@@ -240,7 +242,7 @@ const Tasks = sequelize.define('task', {
len: [3, 10] len: [3, 10]
} }
} }
}) }, { sequelize })
   
Tasks.bulkCreate([ Tasks.bulkCreate([
{name: 'foo', code: '123'}, {name: 'foo', code: '123'},
......
...@@ -4,21 +4,24 @@ While out of the box Sequelize will seem a bit opinionated it's easy to work leg ...@@ -4,21 +4,24 @@ While out of the box Sequelize will seem a bit opinionated it's easy to work leg
## Tables ## Tables
```js ```js
sequelize.define('user', { class User extends Model {}
User.init({
// ... // ...
}, { }, {
tableName: 'users' tableName: 'users',
sequelize,
}); });
``` ```
## Fields ## Fields
```js ```js
sequelize.define('modelName', { class MyModel extends Model {}
MyModel.init({
userId: { userId: {
type: Sequelize.INTEGER, type: Sequelize.INTEGER,
field: 'user_id' field: 'user_id'
} }
}); }, { sequelize });
``` ```
## Primary keys ## Primary keys
...@@ -27,20 +30,22 @@ Sequelize will assume your table has a `id` primary key property by default. ...@@ -27,20 +30,22 @@ Sequelize will assume your table has a `id` primary key property by default.
To define your own primary key: To define your own primary key:
```js ```js
sequelize.define('collection', { class Collection extends Model {}
Collection.init({
uid: { uid: {
type: Sequelize.INTEGER, type: Sequelize.INTEGER,
primaryKey: true, primaryKey: true,
autoIncrement: true // Automatically gets converted to SERIAL for postgres autoIncrement: true // Automatically gets converted to SERIAL for postgres
} }
}); }, { sequelize });
sequelize.define('collection', { class Collection extends Model {}
Collection.init({
uuid: { uuid: {
type: Sequelize.UUID, type: Sequelize.UUID,
primaryKey: true primaryKey: true
} }
}); }, { sequelize });
``` ```
And if your model has no primary key at all you can use `Model.removeAttribute('id');` And if your model has no primary key at all you can use `Model.removeAttribute('id');`
......
...@@ -3,22 +3,25 @@ ...@@ -3,22 +3,25 @@
To define mappings between a model and a table, use the `define` method. Each column must have a datatype, see more about [datatypes][1]. To define mappings between a model and a table, use the `define` method. Each column must have a datatype, see more about [datatypes][1].
```js ```js
const Project = sequelize.define('project', { class Project extends Model {}
Project.init({
title: Sequelize.STRING, title: Sequelize.STRING,
description: Sequelize.TEXT description: Sequelize.TEXT
}) }, { sequelize });
const Task = sequelize.define('task', { class Task extends Model {}
Task.init({
title: Sequelize.STRING, title: Sequelize.STRING,
description: Sequelize.TEXT, description: Sequelize.TEXT,
deadline: Sequelize.DATE deadline: Sequelize.DATE
}) }, { sequelize })
``` ```
Apart from [datatypes][1], there are plenty of options that you can set on each column. Apart from [datatypes][1], there are plenty of options that you can set on each column.
```js ```js
const Foo = sequelize.define('foo', { class Foo extends Model {}
Foo.init({
// instantiating will automatically set the flag to true if not set // instantiating will automatically set the flag to true if not set
flag: { type: Sequelize.BOOLEAN, allowNull: false, defaultValue: true }, flag: { type: Sequelize.BOOLEAN, allowNull: false, defaultValue: true },
...@@ -74,7 +77,7 @@ const Foo = sequelize.define('foo', { ...@@ -74,7 +77,7 @@ const Foo = sequelize.define('foo', {
comment: 'This is a column name that has a comment' comment: 'This is a column name that has a comment'
} }
}) }, { sequelize });
``` ```
The comment option can also be used on a table, see [model configuration][0]. The comment option can also be used on a table, see [model configuration][0].
...@@ -143,7 +146,8 @@ Getters and Setters can be defined in 2 ways (you can mix and match these 2 appr ...@@ -143,7 +146,8 @@ Getters and Setters can be defined in 2 ways (you can mix and match these 2 appr
### Defining as part of a property ### Defining as part of a property
```js ```js
const Employee = sequelize.define('employee', { class Employee extends Model {}
Employee.init({
name: { name: {
type: Sequelize.STRING, type: Sequelize.STRING,
allowNull: false, allowNull: false,
...@@ -160,7 +164,7 @@ const Employee = sequelize.define('employee', { ...@@ -160,7 +164,7 @@ const Employee = sequelize.define('employee', {
this.setDataValue('title', val.toUpperCase()); this.setDataValue('title', val.toUpperCase());
} }
} }
}); }, { sequelize });
Employee Employee
.create({ name: 'John Doe', title: 'senior engineer' }) .create({ name: 'John Doe', title: 'senior engineer' })
...@@ -179,7 +183,26 @@ The `fullName` getter, is an example of how you can define pseudo properties on ...@@ -179,7 +183,26 @@ The `fullName` getter, is an example of how you can define pseudo properties on
Note that the `this.firstname` and `this.lastname` references in the `fullName` getter function will trigger a call to the respective getter functions. If you do not want that then use the `getDataValue()` method to access the raw value (see below). Note that the `this.firstname` and `this.lastname` references in the `fullName` getter function will trigger a call to the respective getter functions. If you do not want that then use the `getDataValue()` method to access the raw value (see below).
```js ```js
const Foo = sequelize.define('foo', { class Foo extends Model {
get fullName() {
return this.firstname + ' ' + this.lastname;
}
set fullName(value) {
const names = value.split(' ');
this.setDataValue('firstname', names.slice(0, -1).join(' '));
this.setDataValue('lastname', names.slice(-1).join(' '));
}
}
Foo.init({
firstname: Sequelize.STRING,
lastname: Sequelize.STRING
}, {
sequelize,
});
// legacy with `sequelize.define`
sequelize.define('Foo', {
firstname: Sequelize.STRING, firstname: Sequelize.STRING,
lastname: Sequelize.STRING lastname: Sequelize.STRING
}, { }, {
...@@ -197,9 +220,10 @@ const Foo = sequelize.define('foo', { ...@@ -197,9 +220,10 @@ const Foo = sequelize.define('foo', {
this.setDataValue('lastname', names.slice(-1).join(' ')); this.setDataValue('lastname', names.slice(-1).join(' '));
} }
} }
}); } );
``` ```
### Helper functions for use inside getter and setter definitions ### Helper functions for use inside getter and setter definitions
* retrieving an underlying property value - always use `this.getDataValue()` * retrieving an underlying property value - always use `this.getDataValue()`
...@@ -233,7 +257,8 @@ Validations are automatically run on `create`, `update` and `save`. You can also ...@@ -233,7 +257,8 @@ Validations are automatically run on `create`, `update` and `save`. You can also
You can define your custom validators or use several built-in validators, implemented by [validator.js][3], as shown below. You can define your custom validators or use several built-in validators, implemented by [validator.js][3], as shown below.
```js ```js
const ValidateMe = sequelize.define('foo', { class ValidateMe extends Model {}
ValidateMe.init({
bar: { bar: {
type: Sequelize.STRING, type: Sequelize.STRING,
validate: { validate: {
...@@ -283,7 +308,7 @@ const ValidateMe = sequelize.define('foo', { ...@@ -283,7 +308,7 @@ const ValidateMe = sequelize.define('foo', {
} }
} }
} }
}); }, { sequelize });
``` ```
Note that where multiple arguments need to be passed to the built-in validation functions, the arguments to be passed must be in an array. But if a single array argument is to be passed, for instance an array of acceptable strings for `isIn`, this will be interpreted as multiple string arguments instead of one array argument. To work around this pass a single-length array of arguments, such as `[['one', 'two']]` as shown above. Note that where multiple arguments need to be passed to the built-in validation functions, the arguments to be passed must be in an array. But if a single array argument is to be passed, for instance an array of acceptable strings for `isIn`, this will be interpreted as multiple string arguments instead of one array argument. To work around this pass a single-length array of arguments, such as `[['one', 'two']]` as shown above.
...@@ -320,7 +345,8 @@ On the other hand, if it is set to allow null (with `allowNull: true`) and that ...@@ -320,7 +345,8 @@ On the other hand, if it is set to allow null (with `allowNull: true`) and that
This means you can, for instance, have a string field which validates its length to be between 5 and 10 characters, but which also allows `null` (since the length validator will be skipped automatically when the value is `null`): This means you can, for instance, have a string field which validates its length to be between 5 and 10 characters, but which also allows `null` (since the length validator will be skipped automatically when the value is `null`):
```js ```js
const User = sequelize.define('user', { class User extends Model {}
User.init({
username: { username: {
type: Sequelize.STRING, type: Sequelize.STRING,
allowNull: true, allowNull: true,
...@@ -328,32 +354,34 @@ const User = sequelize.define('user', { ...@@ -328,32 +354,34 @@ const User = sequelize.define('user', {
len: [5, 10] len: [5, 10]
} }
} }
}); }, { sequelize });
``` ```
You also can conditionally allow `null` values, with a custom validator, since it won't be skipped: You also can conditionally allow `null` values, with a custom validator, since it won't be skipped:
```js ```js
const User = sequelize.define('user', { class User extends Model {}
User.init({
age: Sequelize.INTEGER, age: Sequelize.INTEGER,
name: { name: {
type: Sequelize.STRING, type: Sequelize.STRING,
allowNull: true, allowNull: true,
validate: { validate: {
customValidator: function(value) { customValidator(value) {
if (value === null && this.age !== 10) { if (value === null && this.age !== 10) {
throw new Error("name can't be null unless age is 10"); throw new Error("name can't be null unless age is 10");
} }
}) })
} }
} }
}); }, { sequelize });
``` ```
You can customize `allowNull` error message by setting the `notNull` validator: You can customize `allowNull` error message by setting the `notNull` validator:
```js ```js
const User = sequelize.define('user', { class User extends Model {}
User.init({
name: { name: {
type: Sequelize.STRING, type: Sequelize.STRING,
allowNull: false, allowNull: false,
...@@ -363,7 +391,7 @@ const User = sequelize.define('user', { ...@@ -363,7 +391,7 @@ const User = sequelize.define('user', {
} }
} }
} }
}); }, { sequelize });
``` ```
### Model-wide validations ### Model-wide validations
...@@ -377,7 +405,8 @@ Any error messages collected are put in the validation result object alongside t ...@@ -377,7 +405,8 @@ Any error messages collected are put in the validation result object alongside t
An example: An example:
```js ```js
const Pub = Sequelize.define('pub', { class Pub extends Model {}
Pub.init({
name: { type: Sequelize.STRING }, name: { type: Sequelize.STRING },
address: { type: Sequelize.STRING }, address: { type: Sequelize.STRING },
latitude: { latitude: {
...@@ -399,7 +428,8 @@ const Pub = Sequelize.define('pub', { ...@@ -399,7 +428,8 @@ const Pub = Sequelize.define('pub', {
throw new Error('Require either both latitude and longitude or neither') throw new Error('Require either both latitude and longitude or neither')
} }
} }
} },
sequelize,
}) })
``` ```
...@@ -419,7 +449,8 @@ Such validation could have also been done with a custom validator defined on a s ...@@ -419,7 +449,8 @@ Such validation could have also been done with a custom validator defined on a s
You can also influence the way Sequelize handles your column names: You can also influence the way Sequelize handles your column names:
```js ```js
const Bar = sequelize.define('bar', { /* bla */ }, { class Bar extends Model {}
Bar.init({ /* bla */ }, {
// don't add the timestamp attributes (updatedAt, createdAt) // don't add the timestamp attributes (updatedAt, createdAt)
timestamps: false, timestamps: false,
...@@ -443,14 +474,18 @@ const Bar = sequelize.define('bar', { /* bla */ }, { ...@@ -443,14 +474,18 @@ const Bar = sequelize.define('bar', { /* bla */ }, {
// Enable optimistic locking. When enabled, sequelize will add a version count attribute // Enable optimistic locking. When enabled, sequelize will add a version count attribute
// to the model and throw an OptimisticLockingError error when stale instances are saved. // to the model and throw an OptimisticLockingError error when stale instances are saved.
// Set to true or a string with the attribute name you want to use to enable. // Set to true or a string with the attribute name you want to use to enable.
version: true version: true,
// Sequelize instance
sequelize,
}) })
``` ```
If you want sequelize to handle timestamps, but only want some of them, or want your timestamps to be called something else, you can override each column individually: If you want sequelize to handle timestamps, but only want some of them, or want your timestamps to be called something else, you can override each column individually:
```js ```js
const Foo = sequelize.define('foo', { /* bla */ }, { class Foo extends Model {}
Foo.init({ /* bla */ }, {
// don't forget to enable timestamps! // don't forget to enable timestamps!
timestamps: true, timestamps: true,
...@@ -462,15 +497,19 @@ const Foo = sequelize.define('foo', { /* bla */ }, { ...@@ -462,15 +497,19 @@ const Foo = sequelize.define('foo', { /* bla */ }, {
// And deletedAt to be called destroyTime (remember to enable paranoid for this to work) // And deletedAt to be called destroyTime (remember to enable paranoid for this to work)
deletedAt: 'destroyTime', deletedAt: 'destroyTime',
paranoid: true paranoid: true,
sequelize,
}) })
``` ```
You can also change the database engine, e.g. to MyISAM. InnoDB is the default. You can also change the database engine, e.g. to MyISAM. InnoDB is the default.
```js ```js
const Person = sequelize.define('person', { /* attributes */ }, { class Person extends Model {}
engine: 'MYISAM' Person.init({ /* attributes */ }, {
engine: 'MYISAM',
sequelize
}) })
// or globally // or globally
...@@ -482,8 +521,10 @@ const sequelize = new Sequelize(db, user, pw, { ...@@ -482,8 +521,10 @@ const sequelize = new Sequelize(db, user, pw, {
Finally you can specify a comment for the table in MySQL and PG Finally you can specify a comment for the table in MySQL and PG
```js ```js
const Person = sequelize.define('person', { /* attributes */ }, { class Person extends Model {}
comment: "I'm a table comment!" Person.init({ /* attributes */ }, {
comment: "I'm a table comment!",
sequelize
}) })
``` ```
...@@ -498,10 +539,12 @@ const Project = sequelize.import(__dirname + "/path/to/models/project") ...@@ -498,10 +539,12 @@ const Project = sequelize.import(__dirname + "/path/to/models/project")
// The model definition is done in /path/to/models/project.js // The model definition is done in /path/to/models/project.js
// As you might notice, the DataTypes are the very same as explained above // As you might notice, the DataTypes are the very same as explained above
module.exports = (sequelize, DataTypes) => { module.exports = (sequelize, DataTypes) => {
return sequelize.define("project", { class Project extends sequelize.Model { }
Project.init({
name: DataTypes.STRING, name: DataTypes.STRING,
description: DataTypes.TEXT description: DataTypes.TEXT
}) }, { sequelize });
return Projectl
} }
``` ```
...@@ -509,10 +552,12 @@ The `import` method can also accept a callback as an argument. ...@@ -509,10 +552,12 @@ The `import` method can also accept a callback as an argument.
```js ```js
sequelize.import('project', (sequelize, DataTypes) => { sequelize.import('project', (sequelize, DataTypes) => {
return sequelize.define("project", { class Project extends sequelize.Model {}
Project.init({
name: DataTypes.STRING, name: DataTypes.STRING,
description: DataTypes.TEXT description: DataTypes.TEXT
}) }, { sequelize })
return Project;
}) })
``` ```
...@@ -600,7 +645,8 @@ sequelize.sync({ force: true, match: /_test$/ }); ...@@ -600,7 +645,8 @@ sequelize.sync({ force: true, match: /_test$/ });
Sequelize Models are ES6 classes. You can very easily add custom instance or class level methods. Sequelize Models are ES6 classes. You can very easily add custom instance or class level methods.
```js ```js
const User = sequelize.define('user', { firstname: Sequelize.STRING }); class User extends Model {}
User.init({ firstname: Sequelize.STRING }, { sequelize });
// Adding a class level method // Adding a class level method
User.classLevelMethod = function() { User.classLevelMethod = function() {
...@@ -616,7 +662,8 @@ User.prototype.instanceLevelMethod = function() { ...@@ -616,7 +662,8 @@ User.prototype.instanceLevelMethod = function() {
Of course you can also access the instance's data and generate virtual getters: Of course you can also access the instance's data and generate virtual getters:
```js ```js
const User = sequelize.define('user', { firstname: Sequelize.STRING, lastname: Sequelize.STRING }); class User extends Model {}
User.init({ firstname: Sequelize.STRING, lastname: Sequelize.STRING }, { sequelize });
User.prototype.getFullname = function() { User.prototype.getFullname = function() {
return [this.firstname, this.lastname].join(' '); return [this.firstname, this.lastname].join(' ');
...@@ -630,7 +677,8 @@ User.build({ firstname: 'foo', lastname: 'bar' }).getFullname() // 'foo bar' ...@@ -630,7 +677,8 @@ User.build({ firstname: 'foo', lastname: 'bar' }).getFullname() // 'foo bar'
Sequelize supports adding indexes to the model definition which will be created during `Model.sync()` or `sequelize.sync`. Sequelize supports adding indexes to the model definition which will be created during `Model.sync()` or `sequelize.sync`.
```js ```js
sequelize.define('user', {}, { class User extends Model {}
User.init({}, {
indexes: [ indexes: [
// Create a unique index on email // Create a unique index on email
{ {
...@@ -661,8 +709,9 @@ sequelize.define('user', {}, { ...@@ -661,8 +709,9 @@ sequelize.define('user', {}, {
method: 'BTREE', method: 'BTREE',
fields: ['author', {attribute: 'title', collate: 'en_US', order: 'DESC', length: 5}] fields: ['author', {attribute: 'title', collate: 'en_US', order: 'DESC', length: 5}]
} }
] ],
}) sequelize
});
``` ```
......
...@@ -410,9 +410,12 @@ Project.sum('age', { where: { age: { [Op.gt]: 5 } } }).then(sum => { ...@@ -410,9 +410,12 @@ Project.sum('age', { where: { age: { [Op.gt]: 5 } } }).then(sum => {
When you are retrieving data from the database there is a fair chance that you also want to get associations with the same query - this is called eager loading. The basic idea behind that, is the use of the attribute `include` when you are calling `find` or `findAll`. Lets assume the following setup: When you are retrieving data from the database there is a fair chance that you also want to get associations with the same query - this is called eager loading. The basic idea behind that, is the use of the attribute `include` when you are calling `find` or `findAll`. Lets assume the following setup:
```js ```js
const User = sequelize.define('user', { name: Sequelize.STRING }) class User extends Model {}
const Task = sequelize.define('task', { name: Sequelize.STRING }) User.init({ name: Sequelize.STRING }, { sequelize })
const Tool = sequelize.define('tool', { name: Sequelize.STRING }) class Task extends Model {}
Task.init({ name: Sequelize.STRING }, { sequelize })
class Tool extends Model {}
Tool.init({ name: Sequelize.STRING }, { sequelize })
Task.belongsTo(User) Task.belongsTo(User)
User.hasMany(Task) User.hasMany(Task)
......
...@@ -7,7 +7,8 @@ Scoping allows you to define commonly used queries that you can easily use later ...@@ -7,7 +7,8 @@ Scoping allows you to define commonly used queries that you can easily use later
Scopes are defined in the model definition and can be finder objects, or functions returning finder objects - except for the default scope, which can only be an object: Scopes are defined in the model definition and can be finder objects, or functions returning finder objects - except for the default scope, which can only be an object:
```js ```js
const Project = sequelize.define('project', { class Project extends Model {}
Project.init({
// Attributes // Attributes
}, { }, {
defaultScope: { defaultScope: {
...@@ -26,14 +27,14 @@ const Project = sequelize.define('project', { ...@@ -26,14 +27,14 @@ const Project = sequelize.define('project', {
{ model: User, where: { active: true }} { model: User, where: { active: true }}
] ]
}, },
random: function () { random () {
return { return {
where: { where: {
someNumber: Math.random() someNumber: Math.random()
} }
} }
}, },
accessLevel: function (value) { accessLevel (value) {
return { return {
where: { where: {
accessLevel: { accessLevel: {
...@@ -42,6 +43,7 @@ const Project = sequelize.define('project', { ...@@ -42,6 +43,7 @@ const Project = sequelize.define('project', {
} }
} }
} }
sequelize,
} }
}); });
``` ```
...@@ -175,10 +177,14 @@ Includes are merged recursively based on the models being included. This is a ve ...@@ -175,10 +177,14 @@ Includes are merged recursively based on the models being included. This is a ve
Consider four models: Foo, Bar, Baz and Qux, with has-many associations as follows: Consider four models: Foo, Bar, Baz and Qux, with has-many associations as follows:
```js ```js
Foo = sequelize.define('foo', { name: Sequelize.STRING }; class Foo extends Model {}
Bar = sequelize.define('bar', { name: Sequelize.STRING }; class Bar extends Model {}
Baz = sequelize.define('baz', { name: Sequelize.STRING }; class Baz extends Model {}
Qux = sequelize.define('qux', { name: Sequelize.STRING }; class Qux extends Model {}
Foo.init({ name: Sequelize.STRING }, { sequelize });
Bar.init({ name: Sequelize.STRING }, { sequelize });
Baz.init({ name: Sequelize.STRING }, { sequelize });
Qux.init({ name: Sequelize.STRING }, { sequelize });
Foo.hasMany(Bar, { foreignKey: 'fooId' }); Foo.hasMany(Bar, { foreignKey: 'fooId' });
Bar.hasMany(Baz, { foreignKey: 'barId' }); Bar.hasMany(Baz, { foreignKey: 'barId' });
Baz.hasMany(Qux, { foreignKey: 'bazId' }); Baz.hasMany(Qux, { foreignKey: 'bazId' });
...@@ -282,7 +288,8 @@ User.getPosts({ scope: ['scope1', 'scope2']}); ...@@ -282,7 +288,8 @@ User.getPosts({ scope: ['scope1', 'scope2']});
If you want to create a shortcut method to a scope on an associated model, you can pass the scoped model to the association. Consider a shortcut to get all deleted posts for a user: If you want to create a shortcut method to a scope on an associated model, you can pass the scoped model to the association. Consider a shortcut to get all deleted posts for a user:
```js ```js
const Post = sequelize.define('post', attributes, { class Post extends Model {}
Post.init(attributes, {
defaultScope: { defaultScope: {
where: { where: {
active: true active: true
...@@ -294,7 +301,8 @@ const Post = sequelize.define('post', attributes, { ...@@ -294,7 +301,8 @@ const Post = sequelize.define('post', attributes, {
deleted: true deleted: true
} }
} }
} },
sequelize,
}); });
User.hasMany(Post); // regular getPosts association User.hasMany(Post); // regular getPosts association
......
...@@ -94,7 +94,8 @@ const sequelize = new Sequelize('database', 'username', 'password', { ...@@ -94,7 +94,8 @@ const sequelize = new Sequelize('database', 'username', 'password', {
// The following example: // The following example:
// define: { timestamps: false } // define: { timestamps: false }
// is basically the same as: // is basically the same as:
// sequelize.define(name, attributes, { timestamps: false }) // Model.init(attributes, { timestamps: false });
// sequelize.define(name, attributes, { timestamps: false });
// so defining the timestamps for each model will be not necessary // so defining the timestamps for each model will be not necessary
define: { define: {
underscored: false, underscored: false,
......
/** /**
* The datatypes are used when defining a new model using `Sequelize.define`, like this: * The datatypes are used when defining a new model using `Model.init`, like this:
* ```js * ```js
* sequelize.define('model', { * class MyModel extends MyModel {}
* column: DataTypes.INTEGER * MyModel.init({ column: DataTypes.INTEGER }, { sequelize });
* })
* ``` * ```
* When defining a model you can just as easily pass a string as type, but often using the types defined here is beneficial. For example, using `DataTypes.BLOB`, mean * When defining a model you can just as easily pass a string as type, but often using the types defined here is beneficial. For example, using `DataTypes.BLOB`, mean
* that that column will be returned as an instance of `Buffer` when being fetched by sequelize. * that that column will be returned as an instance of `Buffer` when being fetched by sequelize.
...@@ -17,27 +16,29 @@ ...@@ -17,27 +16,29 @@
* Three of the values provided here (`NOW`, `UUIDV1` and `UUIDV4`) are special default values, that should not be used to define types. Instead they are used as shorthands for * Three of the values provided here (`NOW`, `UUIDV1` and `UUIDV4`) are special default values, that should not be used to define types. Instead they are used as shorthands for
* defining default values. For example, to get a uuid field with a default value generated following v1 of the UUID standard: * defining default values. For example, to get a uuid field with a default value generated following v1 of the UUID standard:
* ```js * ```js
* sequelize.define('model', { * class MyModel extends Model {}
* MyModel.init({
* uuid: { * uuid: {
* type: DataTypes.UUID, * type: DataTypes.UUID,
* defaultValue: DataTypes.UUIDV1, * defaultValue: DataTypes.UUIDV1,
* primaryKey: true * primaryKey: true
* } * }
* }) * }, { sequelize })
* ``` * ```
* There may be times when you want to generate your own UUID conforming to some other algorithm. This is accomplised * There may be times when you want to generate your own UUID conforming to some other algorithm. This is accomplised
* using the defaultValue property as well, but instead of specifying one of the supplied UUID types, you return a value * using the defaultValue property as well, but instead of specifying one of the supplied UUID types, you return a value
* from a function. * from a function.
* ```js * ```js
* sequelize.define('model', { * class MyModel extends Model {}
* MyModel.init({
* uuid: { * uuid: {
* type: DataTypes.UUID, * type: DataTypes.UUID,
* defaultValue: function() { * defaultValue() {
* return generateMyId() * return generateMyId()
* }, * },
* primaryKey: true * primaryKey: true
* } * }
* }) * }, { sequelize })
* ``` * ```
*/ */
...@@ -424,23 +425,24 @@ export const UUIDV4: AbstractDataTypeConstructor; ...@@ -424,23 +425,24 @@ export const UUIDV4: AbstractDataTypeConstructor;
* *
* You could also use it to validate a value before permuting and storing it. Checking password length before hashing it for example: * You could also use it to validate a value before permuting and storing it. Checking password length before hashing it for example:
* ```js * ```js
* sequelize.define('user', { * class User extends Model {}
* User.init({
* password_hash: DataTypes.STRING, * password_hash: DataTypes.STRING,
* password: { * password: {
* type: DataTypes.VIRTUAL, * type: DataTypes.VIRTUAL,
* set: function (val) { * set (val) {
* this.setDataValue('password', val); // Remember to set the data value, otherwise it won't be validated * this.setDataValue('password', val); // Remember to set the data value, otherwise it won't be validated
* this.setDataValue('password_hash', this.salt + val); * this.setDataValue('password_hash', this.salt + val);
* }, * },
* validate: { * validate: {
* isLongEnough: function (val) { * isLongEnough (val) {
* if (val.length < 7) { * if (val.length < 7) {
* throw new Error("Please choose a longer password") * throw new Error("Please choose a longer password")
* } * }
* } * }
* } * }
* } * }
* }) * }, { sequelize });
* ``` * ```
* *
* VIRTUAL also takes a return type and dependency fields as arguments * VIRTUAL also takes a return type and dependency fields as arguments
...@@ -450,7 +452,7 @@ export const UUIDV4: AbstractDataTypeConstructor; ...@@ -450,7 +452,7 @@ export const UUIDV4: AbstractDataTypeConstructor;
* { * {
* active: { * active: {
* type: new DataTypes.VIRTUAL(DataTypes.BOOLEAN, ['createdAt']), * type: new DataTypes.VIRTUAL(DataTypes.BOOLEAN, ['createdAt']),
* get: function() { * get() {
* return this.get('createdAt') > Date.now() - (7 * 24 * 60 * 60 * 1000) * return this.get('createdAt') > Date.now() - (7 * 24 * 60 * 60 * 1000)
* } * }
* } * }
......
...@@ -7,16 +7,17 @@ ...@@ -7,16 +7,17 @@
* that will check the constraints immediately when the data was inserted. * that will check the constraints immediately when the data was inserted.
* *
* ```js * ```js
* sequelize.define('Model', { * class MyModel extends Model {}
* MyModel.init({
* foreign_id: { * foreign_id: {
* type: Sequelize.INTEGER, * type: Sequelize.INTEGER,
* references: { * references: {
* model: OtherModel, * model: OtherModel,
* key: 'id', * key: 'id',
* deferrable: Sequelize.Deferrable.INITIALLY_IMMEDIATE * deferrable: Sequelize.Deferrable.INITIALLY_IMMEDIATE
* }
* } * }
* } * }, { sequelize });
* });
* ``` * ```
* *
* The constraints can be configured in a transaction like this. It will * The constraints can be configured in a transaction like this. It will
......
...@@ -1201,12 +1201,13 @@ export interface ModelAttributeColumnOptions extends ColumnOptions { ...@@ -1201,12 +1201,13 @@ export interface ModelAttributeColumnOptions extends ColumnOptions {
* Usage in object notation * Usage in object notation
* *
* ```js * ```js
* sequelize.define('model', { * class MyModel extends Model {}
* states: { * MyModel.init({
* type: Sequelize.ENUM, * states: {
* values: ['active', 'pending', 'deleted'] * type: Sequelize.ENUM,
* } * values: ['active', 'pending', 'deleted']
* }) * }
* }, { sequelize })
* ``` * ```
*/ */
values?: string[]; values?: string[];
...@@ -1516,7 +1517,8 @@ export abstract class Model<T = any, T2 = any> extends Hooks { ...@@ -1516,7 +1517,8 @@ export abstract class Model<T = any, T2 = any> extends Hooks {
/** /**
* Apply a scope created in `define` to the model. First let's look at how to create scopes: * Apply a scope created in `define` to the model. First let's look at how to create scopes:
* ```js * ```js
* const Model = sequelize.define('model', attributes, { * class MyModel extends Model {}
* MyModel.init(attributes, {
* defaultScope: { * defaultScope: {
* where: { * where: {
* username: 'dan' * username: 'dan'
...@@ -1529,7 +1531,7 @@ export abstract class Model<T = any, T2 = any> extends Hooks { ...@@ -1529,7 +1531,7 @@ export abstract class Model<T = any, T2 = any> extends Hooks {
* stuff: 'cake' * stuff: 'cake'
* } * }
* }, * },
* complexFunction: function(email, accessLevel) { * complexFunction(email, accessLevel) {
* return { * return {
* where: { * where: {
* email: { * email: {
...@@ -1541,7 +1543,8 @@ export abstract class Model<T = any, T2 = any> extends Hooks { ...@@ -1541,7 +1543,8 @@ export abstract class Model<T = any, T2 = any> extends Hooks {
* } * }
* } * }
* } * }
* } * },
* sequelize,
* }) * })
* ``` * ```
* Now, since you defined a default scope, every time you do Model.find, the default scope is appended to * Now, since you defined a default scope, every time you do Model.find, the default scope is appended to
...@@ -2227,9 +2230,10 @@ export abstract class Model<T = any, T2 = any> extends Hooks { ...@@ -2227,9 +2230,10 @@ export abstract class Model<T = any, T2 = any> extends Hooks {
* ways. Consider users and projects from before with a join table that stores whether the project has been * ways. Consider users and projects from before with a join table that stores whether the project has been
* started yet: * started yet:
* ```js * ```js
* const UserProjects = sequelize.define('userprojects', { * class UserProjects extends Model {}
* UserProjects.init({
* started: Sequelize.BOOLEAN * started: Sequelize.BOOLEAN
* }) * }, { sequelize })
* User.hasMany(Project, { through: UserProjects }) * User.hasMany(Project, { through: UserProjects })
* Project.hasMany(User, { through: UserProjects }) * Project.hasMany(User, { through: UserProjects })
* ``` * ```
...@@ -2279,9 +2283,10 @@ export abstract class Model<T = any, T2 = any> extends Hooks { ...@@ -2279,9 +2283,10 @@ export abstract class Model<T = any, T2 = any> extends Hooks {
* associations in two ways. Consider users and projects from before with a join table that stores whether * associations in two ways. Consider users and projects from before with a join table that stores whether
* the project has been started yet: * the project has been started yet:
* ```js * ```js
* const UserProjects = sequelize.define('userprojects', { * class UserProjects extends Model {}
* UserProjects.init({
* started: Sequelize.BOOLEAN * started: Sequelize.BOOLEAN
* }) * }, { sequelize });
* User.belongsToMany(Project, { through: UserProjects }) * User.belongsToMany(Project, { through: UserProjects })
* Project.belongsToMany(User, { through: UserProjects }) * Project.belongsToMany(User, { through: UserProjects })
* ``` * ```
......
...@@ -974,7 +974,8 @@ export class Sequelize extends Hooks { ...@@ -974,7 +974,8 @@ export class Sequelize extends Hooks {
* represents a column. A short table definition might look like this: * represents a column. A short table definition might look like this:
* *
* ```js * ```js
* sequelize.define('modelName', { * class MyModel extends Model {}
* MyModel.init({
* columnA: { * columnA: {
* type: Sequelize.BOOLEAN, * type: Sequelize.BOOLEAN,
* validate: { * validate: {
...@@ -990,7 +991,7 @@ export class Sequelize extends Hooks { ...@@ -990,7 +991,7 @@ export class Sequelize extends Hooks {
* }, * },
* columnB: Sequelize.STRING, * columnB: Sequelize.STRING,
* columnC: 'MY VERY OWN COLUMN TYPE' * columnC: 'MY VERY OWN COLUMN TYPE'
* }) * }, { sequelize })
* *
* sequelize.models.modelName // The model will now be available in models under the name given to define * sequelize.models.modelName // The model will now be available in models under the name given to define
* ``` * ```
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!