The Sequelize library provides easy access to a MySQL database by mapping database entries to objects and vice versa. To put it in a nutshell... it's an ORM (Object-Relational-Mapper). The library is written entirely in JavaScript and can be used in the Node.JS environment.
You can install Sequelize via NPM or just download the code from the git repository and require it's entry file index.js:
# npm:
npm install sequelize
var Sequelize = require("sequelize")
# checkout:
cd path/to/lib
git clone git://github.com/sdepold/sequelize.git
var Sequelize = require(__dirname + "/lib/sequelize/index")This will make the class Sequelize available.
To get the ball rollin' you first have to create an instance of Sequelize. Use it the following way:
var sequelize = new Sequelize('database', 'username'[, 'password'])This will save the passed database credentials and provide all further methods. Furthermore you can specify a non-default host or port and some options:
var sequelize = new Sequelize('database', 'username', 'password', {
host: "my.server.tld",
port: 12345
})
// No need for password?
var sequelize = new Sequelize('database', 'username'[, null])
// All options at once:
var sequelize = new Sequelize('database', 'username', 'password', {
// custom host; default: localhost
host: 'my.server.tld',
// custom port; default: 3306
port: 12345,
// disable logging; default: console.log
logging: false,
// max concurrent database requests; default: 50
maxConcurrentQueries: 100,
// the sql dialect of the database
// - default is 'mysql'
// - currently supported: 'mysql', 'sqlite'
dialect: 'mysql',
// the storage engine for sqlite
// - default ':memory:'
storage: 'path/to/database.sqlite',
// specify options, which are used when sequelize.define is called
// the following example is basically the same as:
// sequelize.define(name, attributes, { timestamps: false })
// so defining the timestamps for each model will be not necessary
define: { timestamps: false },
// similiar for sync: you can define this to always force sync for models
sync: { force: true }
// use pooling in order to reduce db connection overload and to increase speed
// currently only for mysql
pool: { maxConnections: 5, maxIdleTime: 30}
})You can also define a custom function for the logging part. Just pass a function. The first parameter will be the string that is logged.
With v1.3.0 of Sequelize, it is possible to use non-mysql dialects. For now sqlite is available, but other dialects can and will be implemented. Here is how you do it. As describe before, you can pass the wanted dialect to the sequelize instantiation (and for sqlite define the storage):
// All options at once:
var sequelize = new Sequelize('database', 'username', 'password', {
// the sql dialect of the database
// - default is 'mysql'
// - currently supported: 'mysql', 'sqlite', 'postgres'
dialect: 'mysql',
// the storage engine for sqlite
// - default ':memory:'
storage: 'path/to/database.sqlite'
})Due to the default of mysql you have to specifically install the sqlite
library. In order to do this, just change the dependencies in your
package.json and add node-sqlite3:
{
"name": "my project",
// ...
"dependencies": {
// ...
"sqlite3": ">=2.0.0",
"sequelize": "1.3.x",
// ...
}
// ...
}That's it. Besides some strangeness in SQLite you won't notice any differences while using it with sequelize.
Notice: The ">="-operator is used for compatibility to Node 0.4 - 0.6.
When defining the dialect as postgres you'll be able
to access PostgreSQL databases. The used and expected library is
pg. Please install it before switching to
postgres dialect. Again a recommendation for your
package.json.
{
"name": "my project",
// ...
"dependencies": {
// ...
"pg": "0.6.x",
"sequelize": "1.3.x",
// ...
}
// ...
}To define mappings between a model and a table, use the define method. Sequelize will then automatically add the attributes createdAt and updatedAt to it. So you will be able to know when the database entry went into the db and when it was updated the last time.
var Project = sequelize.define('Project', {
title: Sequelize.STRING,
description: Sequelize.TEXT
})
var Task = sequelize.define('Task', {
title: Sequelize.STRING,
description: Sequelize.TEXT,
deadline: Sequelize.DATE
})You can also set some options:
var Foo = sequelize.define('Foo', {
// instantiating will automatically set the flag to true if not set
flag: { type: Sequelize.BOOLEAN, allowNull: false, defaultValue: true},
// default values for dates => current time
myDate: { type: Sequelize.DATE, defaultValue: Sequelize.NOW },
// setting no title will throw an error when trying to save
title: { type: Sequelize.STRING, allowNull: false},
// creating 2 objects with the same value will throw an error
someUnique: {type: Sequelize.STRING, unique: true},
// go on reading for further information about primary keys
identifier: { type: Sequelize.String, primaryKey: true},
// autoIncrement can be used to create auto_incrementing integer columns
incrementMe: { type: Sequelize.INTEGER, autoIncrement: true }
})Sequelize currently supports the following datatypes:
Sequelize.STRING ===> VARCHAR(255) Sequelize.TEXT ===> TEXT Sequelize.INTEGER ===> INTEGER Sequelize.DATE ===> DATETIME Sequelize.BOOLEAN ===> TINYINT(1) Sequelize.FLOAT ===> FLOAT
In v1.3.0 model validations have been added. They allow you to specify format/content/inheritance validations for each attribute of the model. You can perform the validation by calling the validate() method on an instance before saving.
var ValidateMe = sequelize.define('Foo', {
foo: {
type: Sequelize.STRING,
validate: {
is: ["[a-z]",'i'], // will only allow letters
not: ["[a-z]",'i'], // will not allow letters
isEmail: true, // checks for email format (foo@bar.com)
isUrl: true, // checks for url format (http://foo.com)
isIP: true, // checks for IPv4 format (129.89.23.1)
isAlpha: true, // will only allow letters
isAlphanumeric: true // will only allow alphanumeric characters, so "_abc" will fail
isNumeric: true // will only allow numbers
isInt: true, // checks for valid integers
isFloat: true, // checks for valid floating point numbers
isDecimal: true, // checks for any numbers
isLowercase: true, // checks for lowercase
isUppercase: true, // checks for uppercase
notNull: true, // won't allow null
isNull: true, // only allows null
notEmpty: true, // don't allow empty strings
equals: 'specific value', // only allow a specific value
contains: 'foo', // force specific substrings
notIn: 'foo', // force specific substrings
isIn: "foo", // force specific substrings
notContains: 'bar', // don't allow specific substrings
len: [2,10], // only allow values with length between 2 and 10
isUUID: 4, // only allow uuids
isDate: true, // only allow date strings
isAfter: "2011-11-05", // only allow date strings after a specific date
isBefore: "2011-11-05", // only allow date strings before a specific date
max: 23, // only allow values <= 23
min: 23, // only allow values >= 23
isArray: true, // only allow arrays
isCreditCard: true, // check for valid credit card numbers
// custom validations are also possible:
isEven: function(value) {
if(parseInt(value) % 2 != 0)
throw new Error('Only even values are allowed!')
}
}
}
})You can also take influence of the way, Sequelize handles your column names:
var Bar = sequelize.define('Bar', { /* bla */ }, {
// don't add the timestamp attributes (updatedAt, createdAt)
timestamps: false,
// don't delete database entries but set the newly added attribute deletedAt
// to the current date (when deletion was done). paranoid will only work if
// timestamps are not disabled
paranoid: true,
// don't use camelcase for automatically added attributes but underscore style
// so updatedAt will be updated_at
underscored: true,
// disable the modification of tablenames; By default, sequelize will automatically
// transform all passed model names (first parameter of define) into plural.
// if you don't want that, set the following
freezeTableName: true
})You can also store your model definitions in a single file using the import-method. The returned object is exactly the same as defined in the imported file's function.
// in your server file - e.g. app.js
var Project = sequelize.import(__dirname + "/path/to/models/project")
// /path/to/models/project.js
// as you might notice, the DataTypes are the very same as explained above
module.exports = function(sequelize, DataTypes) {
return sequelize.define("Project", {
name: DataTypes.STRING,
description: DataTypes.TEXT
})
}When starting a new project you won't have a database structure and using Sequelize you won't need to. Just specify your model structures and let the library do the rest. Currently supported is the creation and deletion of tables:
// create my nice tables:
Project.sync() // will emit success or failure event
Task.sync() // will emit success or failure event
// force the creation!
Project.sync({force: true}) // this will drop the table first and re-create it afterwards
// drop the tables:
Project.drop() // will emit success or failure event
Task.drop() // will emit success or failure event
// event handling:
Project.[sync|drop]().success(function() {
// ok ... everything is nice!
}).error(function(error) {
// oooh, did you entered wrong database credentials?
})Because synchronizing and dropping all of your tables might be a lot of lines to write, you can also let Sequelize do the work for you:
// create all tables... now!
sequelize.sync() // will emit success or failure
// force it!
sequelize.sync({force: true}) // emit ... nomnomnom
// want to drop 'em all?
sequelize.drop() // I guess you've got it (emit)
// emit handling:
sequelize.[sync|drop]().success(function() {
// woot woot
}).error(function(error) {
// whooops
})Sequelize allows you to pass custom methods to a model and it's instances. Just do the following:
var Foo = sequelize.define('Foo', { /* attributes */}, {
classMethods: {
method1: function(){ return 'smth' }
},
instanceMethods: {
method2: function() { return 'foo' }
}
})
// ==>
Foo.method1()
Foo.build().method2()Finder methods are designed to get data from the database. The returned data isn't just a plain object, but instances of one of the defined classes. Check the next major chapter about instances for further information. But as those things are instances, you can e.g. use the just describe expanded instance methods. So, here is what you can do:
// search for known ids
Project.find(123).success(function(project) {
// project will be an instance of Project and stores the content of the table entry
// with id 123. if such an entry is not defined you will get null
})
// search for attributes
Project.find({ where: {title: 'aProject'} }).success(function(project) {
// project will be the first entry of the Projects table with the title 'aProject' || null
})
// since v1.3.0: only select some attributes and rename one
Project.find({
where: {title: 'aProject'},
attributes: ['id', ['name', 'title']]
}).success(function(project) {
// project will be the first entry of the Projects table with the title 'aProject' || null
// project.title will contain the name of the project
})
// find multiple entries
Project.findAll().success(function(projects) {
// projects will be an array of all Project instances
})
// also possible:
Project.all().success(function(projects) {
// projects will be an array of all Project instances
})
// search for specific attributes - hash usage
Project.findAll({where: {name: 'A Project'}}).success(function(projects) {
// projects will be an array of Project instances with the specified name
})
// search with string replacements
Project.findAll({where: ["id > ?", 25]}).success(function(projects) {
// projects will be an array of Projects having a greater id than 25
})
// search within a specific range
Project.findAll({where: { id: [1,2,3] }}).success(function(projects) {
// projects will be an array of Projects having the id 1, 2 or 3
// this is actually doing an IN query
})
// or
Project.findAll({where: "name = 'A Project'"}).success(function(projects) {
// the difference between this and the usage of hashes (objects) is, that string usage
// is not sql injection safe. so make sure you know what you are doing!
})Of course you can pass a some options to the finder methods, to get more relevant data:
// define the order of the queried data
Project.findAll({order: 'title DESC'})
// limit the results of the query
Project.findAll({limit: 10})
// step over some elements
// this only works with a specified limit
Project.findAll({offset: 10, limit: 2})There is also a method for counting database objects:
Project.count().success(function(c) {
console.log("There are " + c + " projects!")
})
Project.count({where: ["id > ?", 25]}).success(function(c) {
console.log("There are " + c + " projects with an id greater than 25.")
})And here is a method for getting the min and the max value of an attribute:
/*
Let's assume 3 person objects with an attribute age.
The first one is 10 years old,
the second one is 5 years old,
the third one is 40 years old.
*/
Project.min('age').success(function(min) {
// this will return 5
})
Project.max('age').success(function(max) {
// this will return 40
})In order to create instances of defined classes just do as follows.
You might recognize the syntax if you coded Ruby in the past.
Using the build-method will return an unsaved object, which you explicitly have to save.
var project = Project.build({
title: 'my awesome project',
description: 'woot woot. this will make me a rich man'
})
var task = Task.build({
title: 'specify the project idea',
description: 'bla',
deadline: new Date()
})Built instances will automatically get default values when they were defined:
// first define the model
var Task = sequelize.define('Project', {
title: Sequelize.STRING,
rating: { type: Sequelize.STRING, defaultValue: 3 }
})
// now instantiate an object
var task = Task.build({title: 'very important task'})
task.title // ==> 'very important task'
task.rating // ==> 3To get it stored in the database, use the save-method and catch the events … if needed:
project.save().success(function() {
// my nice callback stuff
})
task.save().error(function(error) {
// mhhh, wth!
})
// you can also build, save and access the object with chaining:
Task
.build({ title: 'foo', description: 'bar', deadline: new Date() })
.save()
.success(function(anotherTask) {
// you can now access the currently saved task with the variable anotherTask... nice!
})Besides constructing objects, that needs an explicit save call to get stored in the database, there is also the possibility to do all those steps with one single command. It's called create.
Task.create({ title: 'foo', description: 'bar', deadline: new Date() }).success(function(task) {
// you can now access the newly created task via the variable task
})Now lets change some values and save changes to the database... There are two ways to do that:
// way 1
task.title = 'a very different title now'
task.save().success(function() {})
// way 2
task.updateAttributes({
title: 'a very different title now'
}).success(function() {})In order to define the encoding of a table you can do this:
// charset only
var Person = sequelize.define('Person', { /* attributes */ }, {
charset: 'latin1'
})
// charset + collate; this is still experimental
var Person = sequelize.define('Person', { /* attributes */ }, {
charset: 'utf8',
collate: 'utf8_general_ci'
})
// or of course global
var sequelize = new Sequelize(db, user, pw, {
define: { charset: 'latin1' }
})You can also change the database engine, e.g. to MyISAM. InnoDB is default since v1.2.1.
// charset only
var Person = sequelize.define('Person', { /* attributes */ }, {
engine: 'MYISAM'
})
// or of course global
var sequelize = new Sequelize(db, user, pw, {
define: { engine: 'MYISAM' }
})If you log an instance you will notice, that there are a lot of
additional stuff. In order to hide such stuff and reduce it to the very
interesting information, you can use the values-attribute.
Calling it will return only the values of an instance.
Person.create({
name: 'Rambow',
firstname: 'John'
}).success(function(john) {
console.log(john.values)
})
// result:
// { name: 'Rambow',
// firstname: 'John',
// id: 1,
// createdAt: Tue, 01 May 2012 19:12:16 GMT,
// updatedAt: Tue, 01 May 2012 19:12:16 GMT
// }You can also transform an instance into JSON by using
JSON.stringify(instance). This will basically return the
very same as values.
With Sequelize you can also specify associations between multiple classes.
Doing so will help you to easily access and set those associated objects.
The library therefore provides for each defined class different methods,
which are explained in the following chapters.
NOTE: Associations with models that use custom primaryKeys
(so not the field 'id') are currently unsupported.
One-To-One associations are connecting one source with exactly one target.
In order to define a proper database schema, Sequelize utilizes the methods
belongsTo and hasOne. You can use them as follows:
var User = sequelize.define('User', {/* ... */})
var Project = sequelize.define('Project', {/* ... */})
// One-way associations
Project.hasOne(User)
/*
In this example hasOne will add an attribute ProjectId to the User model!
Furthermore, Project.prototype will gain the methods getUser and setUser according
to the first parameter passed to define. If you have underscore style
enabled, the added attribute will be project_id instead of ProjectId.
You can also define the foreign key, e.g. if you already have an existing
database and want to work on it:
*/
Project.hasOne(User, { foreignKey: 'initiator_id' })
/*
Because Sequelize will use the model's name (first parameter of define) for
the accessor methods, it is also possible to pass a special option to hasOne:
*/
Project.hasOne(User, { as: 'Initiator' })
// Now you will get Project#getInitiator and Project#setInitiator
// Or let's define some self references
var Person = sequelize.define('Person', { /* ... */})
Person.hasOne(Person, {as: 'Father'})
// this will add the attribute FatherId to Person
// also possible:
Person.hasOne(Person, {as: 'Father', foreignKey: 'DadId'})
// this will add the attribute DadId to Person
// In both cases you will be able to do:
Person#setFather
Person#getFather
// Since v1.3.0 you can also chain associations:
Project
.hasOne(User)
.hasOne(Deadline)
.hasOne(Attachment)To get the association working the other way around (so from User to Project), it's necessary to do this:
var User = sequelize.define('User', {/* ... */})
var Project = sequelize.define('Project', {/* ... */})
// One-way back associations
Project.belongsTo(User)
/*
In this example belongsTo will add an attribute UserId to the Project model!
That's the only difference to hasMany. Self references are working the very same way!
*/One-To-Many associations are connecting one source with multiple targets. The targets however are again connected to exactly one specific source.
var User = sequelize.define('User', {/* ... */})
var Project = sequelize.define('Project', {/* ... */})
// OK. Now things get more complicated (not really visible to the user :)).
// First let's define a hasMany association
Project.hasMany(User, {as: 'Workers'})
/*
This will add the attribute ProjectId or project_id to User.
Instances of Project will get the accessors getWorkers and setWorkers.
We could just leave it the way it is and let it be a one-way association.
But we want more! Let's define the other way around:
*/Many-To-Many associations are connecting sources with multiple targets. Furthermore the targets can also have connections to multiple sources.
// again the Project association to User
Project.hasMany(User, { as: 'Workers' })
// now comes the association between User and Project
User.hasMany(Project)
/*
This will remove the attribute ProjectId (or project_id) from User and create
a new model called ProjectsUsers with the equivalent foreign keys ProjectId
(or project_id) and UserId (or user_id). If the attributes are camelcase or
not depends on the Model it represents.
Now you can use Project#getWorkers, Project#setWorkers, User#getTasks and
User#setTasks.
*/
// Of course you can also define self references with hasMany:
Person.hasMany(Person, { as: 'Children' })
// This will create the table ChildrenPersons which stores the ids of the objects.Because Sequelize is doing a lot of magic, you have to call
Sequelize#sync after setting the associations!
Doing so will allow you the following:
Project.hasMany(Task)
Task.hasMany(Project)
Project.create()...
Task.create()...
Task.create()...
// save them... and then:
project.setTasks([task1, task2]).success(function() {
// saved!
})
// ok now they are save... how do I get them later on?
project.getTasks().success(function(associatedTasks) {
// associatedTasks is an array of tasks
})To remove created associations you can just call the set method without a specific id:
// remove the association with task1
project.setTasks([task2]).success(function(associatedTasks) {
// you will get task2 only
})
// remove 'em all
projects.setTasks([]).success(function(associatedTasks) {
// you will get an empty array
})
// or remove 'em more directly
projects.removeTask(task1).success(function() {
// it's gone
})
// and add 'em again
projects.addTask(task1).success(function() {
// it's back again
})You can of course also do it vice versa:
// project is associated with task1 and task2
task2.setProject(null).success(function() {
// and it's gone
})For hasOne/belongsTo its basically the same:
Task.hasOne(User, {as: "Author"})
Task#setAuthor(anAuthor)Sequelize v1.3.0 introduced migrations. With those mechanism you can transform your existing database into another state and vice versa. Those state transitions are saved in migration files, which describe the way how to get to the new state and how to revert the changes in order to get back to the old state.
In order to run migrations, sequelize comes with a handy binary file which can setup your project and run migrations. The following snippet shows the possible things:
sequelize -h sequelize --help --> prints the help sequelize -V sequelize --version --> prints the version sequelize -i sequelize --init --> creates a migration folder --> creates a config folder --> saves a config.json inside the config folder sequelize -i -f sequelize --init --force --> forced creation of migration and config folder --> existing data will be deleted first sequelize -m sequelize --migrate --> needs a valid config.json --> runs pending migrations --> saves successfully executed migrations inside the database sequelize -m -u sequelize --migrate --undo --> needs a valid config.json --> reverts the last successfull migration --> when there were multiple executed migrations, all of them are reverted
The following skeleton shows a typical migration file. All migrations are expected to be located in a folder called "migrations" at the very top of the project.
module.exports = {
up: function(migration, DataTypes) {
// logic for transforming into the new state
},
down: function(migration, DataTypes) {
// logic for reverting the changes
}
}The passed migration object can be used to modify the database.
The DataTypes object stores the available data types such as
STRING or INTEGER. The available methods of the migration object are the
following.
Using the migration object describe before, you will have access
to most of already introduced functions. Furthermore there are some other
methods, which are designed to actually change the database schema.
This method allows creation of new tables. It is allowed to pass simple or complex attribute definitions. You can define the encoding of the table and the table's engine via options.
migration.createTable(
'nameOfTheNewTable',
{
attr1: DataTypes.STRING,
attr2: DataTypes.INTEGER,
attr3: {
type: DataTypes.BOOLEAN,
defaultValue: false,
allowNull: false
}
},
{
engine: 'MYISAM', // default: 'InnoDB'
charset: 'latin1' // default: null
}
)This method allows deletion of an existing table.
migration.dropTable('nameOfTheExistingTable')This method allows deletion of all existing tables in the database.
migration.dropAllTables()
This method allows renaming of an existing table.
migration.renameTable('Person', 'User')This method returns the name of all existing tables in the database.
migration.showAllTables().success(function(tableNames) {})This method returns an array of hashes containing information about all attributes in the table.
migration.describeTable('Person').success(function(attributes) {
/*
tableNames will be something like:
[ { Field: 'name',
Type: 'varchar(255)',
Null: 'YES',
Key: '',
Default: null,
Extra: '' },
{ Field: 'isBetaMember',
Type: 'tinyint(1)',
Null: 'NO',
Key: '',
Default: '0',
Extra: '' } ]
*/
})This method allows adding columns to an existing table. The data type can be simple or complex.
migration.addColumn(
'nameOfAnExistingTable',
'nameOfTheNewAttribute',
DataTypes.STRING
)
// or
migration.addColumn(
'nameOfAnExistingTable',
'nameOfTheNewAttribute',
{
type: DataTypes.STRING,
allowNull: false
}
)This method allows deletion of a specific column of an existing table
migration.removeColumn('Person', 'signature')This method changes the meta data of an attribute. It is possible to change the default value, allowance of null or the data type. Please make sure, that you are completely describing the new data type. Missing information are expected to be defaults.
migration.addColumn(
'nameOfAnExistingTable',
'nameOfAnExistingAttribute',
DataTypes.STRING
)
// or
migration.addColumn(
'nameOfAnExistingTable',
'nameOfAnExistingAttribute',
{
type: DataTypes.FLOAT,
allowNull: false,
default: 0.0
}
)This methods allows renaming attributes.
migration.renameColumn('Person', 'signature', 'sig')This methods creates indexes for specific attributes of a table. The index name will be automatically generate if it is not passed via in the options (indexName).
migration.addIndex('Person', ['firstname', 'lastname'])
// will create the index person_firstname_lastname
// or with options
&nbp;
migration.addIndex(
'Person',
['firstname', 'lastname'],
{
indexName: 'SuperDuperIndex'
}
)
// will create the index SuperDuperIndexThis method returns all indexes on the table.
migration.showIndex('Person')This method deletes an existing index of a table.
migration.removeIndex('Person', 'SuperDuperIndex')
// or
migration.removeIndex('Person', ['firstname', 'lastname'])Because you will want to save several items at once and just go on after all of them are saved, Sequelize provides a handy helper for that:
var chainer = new Sequelize.Utils.QueryChainer
chainer.add(/* Query | EventEmitter */)
chainer.run().success(function(){}).error(function(errors){})And a real example:
var chainer = new Sequelize.Utils.QueryChainer
var Task = sequelize.define('Task', /* ... */)
chainer
.add(Task.drop())
.add(Task.sync())
for(var i = 0; i < 20; i++)
chainer.add(Task.create({}))
chainer
.run()
.success(function(){})
.error(function(errors){})It is also possible to force a serial run of the query chainer by using the following syntax:
new Sequelize.Utils.QueryChainer()
.add(Model, 'function', [param1, param2])
.add(Model, 'function2', [param1, param2])
.runSerially()
.success(function() { /* no problems :) */ })
.error(function(err) { /* hmm not good :> */ })
// and with options:
new Sequelize.Utils.QueryChainer()
.add(Model, 'function', [param1, param2], {
// Will be executed before Model#function is called
before: function(model) {},
/*
Will be executed after Model#function was called
and the function emitted a success or error event.
If the following success option is passed, the function
will be executed after the success function.
*/
after: function(migration) {},
// Will be executed if Model#function emits a success event.
success: function(migration, callback) {}
})
// skipOnError: don't execute functions once one has emitted an failure event.
.runSerially({ skipOnError: true })
.success(function() { /* no problems :) */ })
.error(function(err) { /* hmm not good :> */ })Sequelize is compatible to the following versions of Node.JS:
Since v1.3.0 there are multiple ways of adding listeners to asynchronous requests. First of all, each time you call a finder method or save an object, sequelize triggers asynchronous logic. To react to the success or the failure of the request, you can do the following:
// the old, pre-v1.3.0 way
Model.findAll().on('success', function(models) { /* foo */ })
Model.findAll().on('failure', function(err) { /* bar */ })
// the new, >=v1.3.0 way
// each one is valid
Model.findAll().on('success', function(models) { /* foo */ })
Model.findAll().success(function(models) { /* foo */ })
Model.findAll().ok(function(models) { /* foo */ })
Model.findAll().on('failure', function(err) { /* bar */ })
Model.findAll().error(function(err) { /* bar */ })
Model.findAll().failure(function(err) { /* bar */ })
Model.findAll().fail(function(err) { /* bar */ })
/*
Please notice:
I will replace .on('failure') with .on('error') in future releases.
This will be done, due to being more native in the node environment.
Doing so will throw an error each time you don't listen for the 'error'-
event.
*/If you want to keep track about latest development of sequelize or to just discuss things with other sequelize users you might want to take a look at the following resources.
You are using Sequelize? Let me know and get listed here! Just send me a private message on GitHub :-)