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

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
...@@ -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!