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

Commit ebab9d9e by Jan Aagaard Meier

Some api doc work on DAOfactory and hooks

1 parent c0b82bd5
......@@ -8,6 +8,14 @@ var Utils = require("./utils")
, QueryTypes = require('./query-types')
module.exports = (function() {
/**
* A DAOFactory represents a table in the database. Sometimes you might also see it refererred to as model, or simply as factory. This class should _not_ be instantiated directly, It is created using `sequelize.define`, and already created models can be loaded using `sequelize.import`
*
* @class DAOFactory
* @mixes {Hooks}
* @mixes {Assocations}
* @mixes http://nodejs.org/api/events.html#events_class_events_eventemitter
*/
var DAOFactory = function(name, attributes, options) {
this.options = Utils._.extend({
timestamps: true,
......@@ -484,10 +492,17 @@ module.exports = (function() {
/**
* Search for an instance.
*
* @param {Object} options Options to describe the scope of the search.
* @param {Array} include A list of associations which shall get eagerly loaded. Supported is either { include: [ DaoFactory1, DaoFactory2, ...] } or { include: [ { daoFactory: DaoFactory1, as: 'Alias' } ] }.
* @param {Object} set the query options, e.g. raw, specifying that you want raw data instead of built DAOs
* @return {Object} A promise which fires `success`, `error`, `complete` and `sql`.
* @param {Object|Number} options A hush of options to describe the scope of the search, or a number to search by id.
* @param {Object} [options.where]
* @param {Array<String>} [options.attributes] A list of the attributes that you want to select
* @param {Array<Object|DAOFactory>} [options.include] A list of associations which shall get eagerly loaded. Supported is either { include: [ DaoFactory1, DaoFactory2, ...] } or { include: [ { daoFactory: DaoFactory1, as: 'Alias' } ] }.
* @param {String|Array} [options.order]
* @param {Number} [options.limit]
* @param {Number} [options.offset]
* @param {Object} queryOptions set the query options, e.g. raw, specifying that you want raw data instead of built DAOs. See sequelize.query for options
* @param {Transaction} queryOptions.transaction
*
* @return {EventEmitter} Fires `success`, `error` and `sql`. Upon success, a DAO will be return to the sucess listener
*/
DAOFactory.prototype.find = function(options, queryOptions) {
var hasJoin = false
......@@ -657,6 +672,18 @@ module.exports = (function() {
return this.aggregate(field, 'sum', options)
}
/**
* Builds a new model instance. Values is an object of key value pairs, must be defined but can be empty.
* @param {Object} values
* @param {Object} [options]
* @param {Boolean} [options.raw=false] If set to true, values will ignore field and virtual setters.
* @param {Boolean} [options.isNewRecord=true]
* @param {Boolean} [options.isDirty=true]
* @param {Array} [options.include] an array of include options - Used to build prefetched/included model instances
*
* @return {DAO}
*/
DAOFactory.prototype.build = function(values, options) {
options = options || { isNewRecord: true, isDirty: true }
......@@ -667,6 +694,24 @@ module.exports = (function() {
return new this.DAO(values, options)
}
/**
* Builds a new model instance and calls save on it.
* @see {DAO#build}
* @see {DAO#save}
*
* @param {Object} values
* @param {Object} [options]
* @param {Boolean} [options.raw=false] If set to true, values will ignore field and virtual setters.
* @param {Boolean} [options.isNewRecord=true]
* @param {Boolean} [options.isDirty=true]
* @param {Array} [options.fields] If set, only columns matching those in fields will be saved
* @param {Array} [options.include] an array of include options - Used to build prefetched/included model instances
* @param {Transaction} [options.transaction]
*
* @return {EventEmitter} Fires `success`, `error` and `sql`. Upon success, the DAO will be return to the success listener
*/
DAOFactory.prototype.create = function(values, fieldsOrOptions) {
Utils.validateParameter(values, Object, { optional: true })
Utils.validateParameter(fieldsOrOptions, Object, { deprecated: Array, optional: true, index: 2, method: 'DAOFactory#create' })
......@@ -766,17 +811,16 @@ module.exports = (function() {
}
/**
* Create and insert multiple instances
* Create and insert multiple instances in bulk
*
* @param {Array} records List of objects (key/value pairs) to create instances from
* @param {Array} fields Fields to insert (defaults to all fields)
* @return {Object} A promise which fires `success`, `error`, `complete` and `sql`.
*
* Note: the `success` handler is not passed any arguments. To obtain DAOs for
* the newly created values, you will need to query for them again. This is
* because MySQL and SQLite do not make it easy to obtain back automatically
* generated IDs and other default values in a way that can be mapped to
* multiple records
* @param {Array} records List of objects (key/value pairs) to create instances from
* @param {Object} [options]
* @param {Array} [options.fields] Fields to insert (defaults to all fields)
* @param {Boolean} [options.validate=false] Should each row be subject to validation before it is inserted. The whole insert will fail if one row fails validation
* @param {Boolean} [options.hooks=false] Run before / after bulkCreate hooks?
* @param {Boolean} [options.ignoreDuplicates=false] Ignore duplicate values for primary keys? (not supported by postgres)
*
* @return {EventEmitter} Fires `success`, `error` and `sql`. The success` handler is not passed any arguments. To obtain DAOs for the newly created values, you will need to query for them again. This is because MySQL and SQLite do not make it easy to obtain back automatically generated IDs and other default values in a way that can be mapped to multiple records
*/
DAOFactory.prototype.bulkCreate = function(records, fieldsOrOptions, options) {
Utils.validateParameter(fieldsOrOptions, Object, { deprecated: Array, optional: true, index: 2, method: 'DAOFactory#bulkCreate' })
......@@ -949,12 +993,13 @@ module.exports = (function() {
/**
* Delete multiple instances
*
* @param {Object} where Options to describe the scope of the search.
* @param {Object} options Possible options are:
- hooks: If set to true, destroy will find all records within the where parameter and will execute before/afterDestroy hooks on each row
- limit: How many rows to delete
- truncate: If set to true, dialects that support it will use TRUNCATE instead of DELETE FROM. If a table is truncated the where and limit options are ignored
* @return {Object} A promise which fires `success`, `error`, `complete` and `sql`.
* @param {Object} where Options to describe the scope of the search.
* @param {Object} options:
* @param {Boolean} options.hooks If set to true, destroy will find all records within the where parameter and will execute before/afterDestroy hooks on each row
* @param {Number} options.limit How many rows to delete
* @param {Boolean} options.truncate If set to true, dialects that support it will use TRUNCATE instead of DELETE FROM. If a table is truncated the where and limit options are ignored
*
* @return {EventEmitter} Fires `success`, `error` and `sql`.
*/
DAOFactory.prototype.destroy = function(where, options) {
options = options || {}
......@@ -1070,9 +1115,13 @@ module.exports = (function() {
/**
* Update multiple instances
*
* @param {Object} attrValueHash A hash of fields to change and their new values
* @param {Object} where Options to describe the scope of the search.
* @return {Object} A promise which fires `success`, `error`, `complete` and `sql`.
* @param {Object} attrValueHash A hash of fields to change and their new values
* @param {Object where Options to describe the scope of the search. Note that these options are not wrapped in a { where: ... } is in find / findAll calls etc. This is probably due to change in 2.0
* @param {Object} options
* @param {Boolean} [options.validate=true] Should each row be subject to validation before it is inserted. The whole insert will fail if one row fails validation
* @param {Boolean} [options.hooks=false] Run before / after bulkUpdate hooks?
*
* @return {EventEmitter} A promise which fires `success`, `error` and `sql`.
*/
DAOFactory.prototype.update = function(attrValueHash, where, options) {
var self = this
......
......@@ -10,13 +10,13 @@ module.exports = (function() {
* This class represents an single instance, a database column. You might see it referred to as both DAO and instance.
*
* DAO instances operate with the concept of a `dataValues` property, which stores the actual values represented by this DAO. By default, the values from dataValues can also be accessed directly from the DAO, that is:
```js
instance.field
// is the same as
instance.get('field')
// is the same as
instance.getDataValue('field')
```
* ```js
* instance.field
* // is the same as
* instance.get('field')
* // is the same as
* instance.getDataValue('field')
* ```
* However, if getters and/or setters are defined for `field` they will be invoked, instead of returning the value from `dataValues`.
* @see {Sequelize#define} Sequelize#define for more information about getters and setters
......
var Utils = require("./utils")
/**
* Hooks are function that are called before and after (bulk-) creation/updating/deletion and validation. Hooks can be added to you models in three ways:
* 1. By specifying them as options in sequelize.define
* 2. By calling `hook()` with a string and your hook handler function
* 3. By calling the function with the same name as the hook you want
* ```js
* // Method 1
* sequelize.define(name, { attributes }, {
* hooks: {
* beforeBulkCreate: function () {
* // can be a single function
* },
* beforeValidate: [
* function () {},
* function() {} // Or an array of several
* ]
* }
* })
*
* // Method 2
* Model.hook('afterDestroy', function () {})
*
* // Method 3
* Model.afterBulkUpdate(function () {})
* ```
*
* @see {Sequelize#define}
* @mixin Hooks
*/
var Hooks = module.exports = function(){}
var hookAliases = {
beforeDelete: "beforeDestroy",
......@@ -65,11 +96,21 @@ Hooks.runHooks = function() {
run(hooks[tick])
}
// Alias for `.addHook`
/**
* Alias of addHook
* @see {Hooks#addHook}
*/
Hooks.hook = function() {
Hooks.addHook.apply(this, arguments)
}
/**
* Add a hook to the model
*
* @param {String} hooktype
* @param {String} [name] Provide a name for the hooks function. This serves no purpose other than the ability/capability for the future to order hooks based on either a priority system or by before/after a specific hook.
* @param {Function} fn The hook function
*/
Hooks.addHook = function(hookType, name, fn) {
if (typeof name === "function") {
fn = name
......@@ -88,6 +129,11 @@ Hooks.addHook = function(hookType, name, fn) {
this.options.hooks[hookType][this.options.hooks[hookType].length] = !!name ? {name: name, fn: method} : method
}
/**
* A hook that is run before validation
* @param {String} name
* @param {Function} fn A callback function that is called with model, callback(err)
*/
Hooks.beforeValidate = function(name, fn) {
Hooks.addHook.call(this, 'beforeValidate', name, fn)
}
......
......@@ -158,7 +158,7 @@ module.exports = (function() {
/**
* An object of different query types. This is used when doing raw queries (sequlize.query). If no type is provided to .query, sequelize will try to guess the correct type based on your SQL. This might not always work if you query is formatted in a special way
* @see sequelize#query
* @see {Sequelize#query}
* @see {QueryTypes}
*/
Sequelize.QueryTypes = QueryTypes
......@@ -252,6 +252,7 @@ module.exports = (function() {
* For more about instance and class methods see http://sequelizejs.com/docs/latest/models#expansion-of-models
*
* @see {DataTypes}
* @see {Hooks}
* @param {String} daoName
* @param {Object} attributes An object, where each attribute is a column of the table. Each column can be either a DataType, a string or a type-description object, with the properties described below:
* @param {String|DataType|Object} attributes.column The description of a database column
......@@ -288,6 +289,7 @@ module.exports = (function() {
* @param {Strng} [options.charset]
* @param {String} [options.comment]
* @param {String} [options.collate]
* @param {Object} [options.hooks] An object of hook function that are called before and after certain lifecycle events. The possible hooks are: beforeValidate, afterValidate, beforeBulkCreate, beforeBulkDestroy, beforeBulkUpdate, beforeCreate, beforeDestroy, beforeUpdate, afterCreate, afterDestroy, afterUpdate, afterBulkCreate, afterBulkDestory and afterBulkUpdate. See Hooks for more information about hook functions and their signatures. Each property can either be a function, or an array of function.
*
* @return {DaoFactory}
* TODO validation
......@@ -621,7 +623,7 @@ module.exports = (function() {
/**
* Creates a object representing a column in the DB. This is usefull in sequelize.fn, since raw string arguments to that will be escaped.
* @see Sequelize#fn
* @see {Sequelize#fn}
*
* @method col
* @param {String} col The name of the column
......
......@@ -5,10 +5,16 @@ var markdox = require('markdox')
var getTag = function(tags, tagName) {
return _.find(tags, function (tag) {
return tag.type === tagName
return tag.type === tagName;
});
};
var getTags = function(tags, tagName) {
return _.where(tags, function (tag) {
return tag.type === tagName;
});
}
// TODO multiple @see tags
var options = {
output: 'output.md',
......@@ -18,7 +24,9 @@ var options = {
docfile.members = [];
docfile.javadoc.forEach(function(javadoc, index){
// Find constructor tags
docfile.javadoc[index].isConstructor = getTag(javadoc.raw.tags, 'constructor') !== undefined;
javadoc.isConstructor = getTag(javadoc.raw.tags, 'constructor') !== undefined;
javadoc.isMixin = getTag(javadoc.raw.tags, 'mixin') !== undefined;
javadoc.mixes = getTags(javadoc.raw.tags, 'mixes');
// Only show params without a dot in them (dots means attributes of object, so no need to clutter the co)
var params = []
......@@ -30,26 +38,28 @@ var options = {
javadoc.paramStr = params.join(', ');
// Handle linking in comments
if (javadoc.see) {
if (javadoc.see.indexOf('{') === 0){
var see = javadoc.see.split('}')
see[0] = see[0].substring(1)
if (javadoc.see.indexOf('www') !== -1) {
javadoc.seeExternal = true
} else {
javadoc.seeExternal = false
}
javadoc.seeURL = see[0]
javadoc.see = getTags(javadoc.raw.tags, 'see');
javadoc.see.forEach(function (see, i, collection) {
collection[i] = {}
if (see[1] !== "") {
javadoc.seeText = see[1]
if (see.local) {
collection[i].external = false
if (see.local.indexOf('{') === 0){
var _see = see.local.split('}')
_see[0] = _see[0].substring(1)
collection[i].url = _see[0]
collection[i].text = see.local
} else {
javadoc.seeText = see[0]
collection[i].url = false
collection[i].text = see.local
}
} else {
javadoc.seeURL = false
collection[i].external = true
}
}
})
// Set a name for properties
if (!javadoc.name) {
......@@ -60,7 +70,7 @@ var options = {
}
if (!javadoc.isClass) {
docfile.members.push(javadoc.name)
docfile.members.push(javadoc.name + '(' + javadoc.paramStr + ')')
}
});
......@@ -69,7 +79,7 @@ var options = {
template: 'output.md.ejs'
};
markdox.process('./lib/sequelize.js', options, function(){
markdox.process(process.argv[2] || './lib/hooks.js', options, function(){
md = fs.readFileSync('output.md').toString();
fs.writeFileSync('out.html', ghm.parse(md));
......
......@@ -14,10 +14,22 @@
<?= comment.description ?>
<? if (comment.mixes.length) { ?>
### Mixes:
<? comment.mixes.forEach(function (mix) { mix = mix.string ?>
<? if (mix.indexOf('www') !== -1 || mix.indexOf('http') !== -1) { -?>
* <a href="<?= mix ?>"><?= mix ?></a>
<? } else { -?>
* <a href="https://github.com/sequelize/sequelize/wiki/API-Reference-<?= mix ?>"><?= mix.substring(1, mix.length -1) ?></a>
<? } ?>
<? }) ?>
<? } ?>
<? if (comment.isClass) { ?>
### Members:
<? doc.members.forEach(function (member) { ?>
* <a href="#<?= member ?>"><?= member ?></a><? }) ?>
<? doc.members.forEach(function (member) { -?>
* <a href="#<?= member ?>"><?= member ?></a>
<? }) -?>
<? } ?>
<? if (comment.deprecated) { ?>
......@@ -32,17 +44,18 @@
Version: <?= comment.version ?>
<? } ?>
<? if (comment.see) { ?>
<? if (comment.seeURL !== false) { ?>
<? if (comment.seeExternal) { ?>
See: <a href="<?= comment.seeURL ?>"><?= comment.seeText ?></a>
<? } else { ?>
See: <a href="https://github.com/sequelize/sequelize/wiki/API-Reference-<?= comment.seeURL ?>"><?= comment.seeText ?></a>
<? } ?>
<? } else { ?>
See: <?= comment.see ?>
<? } ?>
<? } ?>
<? if (comment.see.length) { ?>See:<? } ?>
<? comment.see.forEach(function (see) { -?>
<? if (see.url !== false) { -?>
<? if (see.external) { -?>
* <a href="<?= see.url ?>"><?= see.text ?></a>
<? } else { -?>
* <a href="https://github.com/sequelize/sequelize/wiki/API-Reference-<?= see.url ?>"><?= see.text ?></a>
<? } -?>
<? } else { -?>
* <?= see.text ?>
<? } -?>
<? }) -?>
<? if (comment.paramTags.length > 0) { ?>
#### Params:
......@@ -70,7 +83,7 @@
------
<? }) ?>
_This document is automatically generated based on source code comments. Please do not edit it directly, as your changes will be ignored. Please write on [IRC](irc://irc.freenode.net/#sequelizejs), open an issue or a create a pull request if you feel something can be improved. For help on how to write source code documentation see [JSDoc](http://usejsdoc.org), [dox](https://github.com/visionmedia/dox) and [markdox](https://github.com/cbou/markdox)_
_This document is automatically generated based on source code comments. Please do not edit it directly, as your changes will be ignored. Please write on [IRC](irc://irc.freenode.net/#sequelizejs), open an issue or a create a pull request if you feel something can be improved. For help on how to write source code documentation see [JSDoc](http://usejsdoc.org) and [markdox](https://github.com/cbou/markdox)_
_This documentation was automagically created on <?= new Date().toString() ?>_
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!