sequelize/sequelize — pull request #1841 by overlookmotel (2014-05-31 12:22:57+00:00)
Title: Changes to hooks

This PR does the following:

### Model#bulkCreate bug

`Model.bulkCreate()` with option `{ hooks: true }`, was running the beforeCreate and afterCreate hooks twice each. This PR fixes that.

### Model#update bug

When doing `Model#update()` (i.e. bulk update) with option `{ hooks: true }`, any changes made to the daos by the beforeUpdate hooks were not reflected in what actually gets written to the DB.

So... I have added code in `Model#update()` to run the beforeUpdate hooks on each dao and take note of any changes they make to the daos. If the changes to all the daos are consistent (i.e. if they alter every dao in the same way), then `attrValueHash` is altered to reflect these changes and a bulk update is run (i.e. a single SQL statement to alter all the rows at once). If the daos are being changed inconsistently, so it's not possible to alter them all with a single SQL statement, a dao is built for each record and then `.save()` run on each.

### Hooks / individualHooks options

For all functions which support hooks, you can now pass option `{ hooks: false }` if you want the hooks to be skipped. This option otherwise defaults to true.

For bulk operations `Model#bulkCreate()`, `Model#update()` and `Model#destroy()`, if you want individual hooks to fire on each individual row, use option `{ individualHooks: true }` (defaults to false). This is what `{ hooks: true }` used to do, but with a new name that is hopefully more descriptive!

### Code re-factor

I've chopped about the code in `Model#bulkCreate()` `Model#update()` etc to make it more promise-y and in more sequentially ordered which hopefully makes it easier to understand.

Also, where rows are created/updated individually or hooks are being run on individual rows, this is now done in parallel on all rows simultaneously, rather than in series, which should be faster.