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

Commit 5e5f00f6 by Jan Aagaard Meier

Merge pull request #4593 from subjectix/doc-api-improvement

Doc association api improvements. Fixes #4591
2 parents 11aef712 136f8696
...@@ -20,6 +20,8 @@ var Utils = require('./../utils') ...@@ -20,6 +20,8 @@ var Utils = require('./../utils')
* role: Sequelize.STRING * role: Sequelize.STRING
* }); * });
* User.belongsToMany(Project, { through: UserProject }); * User.belongsToMany(Project, { through: UserProject });
* Project.belongsToMany(User, { through: UserProject });
* // through is required!
* *
* user.addProject(project, { role: 'manager', transaction: t }); * user.addProject(project, { role: 'manager', transaction: t });
* ``` * ```
...@@ -195,7 +197,7 @@ var BelongsToMany = function(source, target, options) { ...@@ -195,7 +197,7 @@ var BelongsToMany = function(source, target, options) {
this.accessors = { this.accessors = {
/** /**
* Get everything currently associated with this, using an optional where clause * Get everything currently associated with this, using an optional where clause.
* *
* @param {Object} [options] * @param {Object} [options]
* @param {Object} [options.where] An optional where clause to limit the associated models * @param {Object} [options.where] An optional where clause to limit the associated models
...@@ -205,7 +207,7 @@ var BelongsToMany = function(source, target, options) { ...@@ -205,7 +207,7 @@ var BelongsToMany = function(source, target, options) {
*/ */
get: 'get' + plural, get: 'get' + plural,
/** /**
* Set the associated models by passing an array of instances or their primary keys. Everything that it not in the passed array will be un-associated * Set the associated models by passing an array of instances or their primary keys. Everything that it not in the passed array will be un-associated.
* *
* @param {Array<Instance|String|Number>} [newAssociations] An array of instances or primary key of instances to associate with this. Pass `null` or `undefined` to remove all associations. * @param {Array<Instance|String|Number>} [newAssociations] An array of instances or primary key of instances to associate with this. Pass `null` or `undefined` to remove all associations.
* @param {Object} [options] Options passed to `through.findAll`, `bulkCreate`, `update` and `destroy`. Can also hold additional attributes for the join table * @param {Object} [options] Options passed to `through.findAll`, `bulkCreate`, `update` and `destroy`. Can also hold additional attributes for the join table
...@@ -215,7 +217,7 @@ var BelongsToMany = function(source, target, options) { ...@@ -215,7 +217,7 @@ var BelongsToMany = function(source, target, options) {
*/ */
set: 'set' + plural, set: 'set' + plural,
/** /**
* Associate several instances with this * Associate several instances with this.
* *
* @param {Array<Instance|String|Number>} [newAssociations] An array of instances or primary key of instances to associate with this. Pass `null` or `undefined` to remove all associations. * @param {Array<Instance|String|Number>} [newAssociations] An array of instances or primary key of instances to associate with this. Pass `null` or `undefined` to remove all associations.
* @param {Object} [options] Options passed to `through.findAll`, `bulkCreate`, and `update` `destroy`. Can also hold additional attributes for the join table * @param {Object} [options] Options passed to `through.findAll`, `bulkCreate`, and `update` `destroy`. Can also hold additional attributes for the join table
...@@ -225,7 +227,7 @@ var BelongsToMany = function(source, target, options) { ...@@ -225,7 +227,7 @@ var BelongsToMany = function(source, target, options) {
*/ */
addMultiple: 'add' + plural, addMultiple: 'add' + plural,
/** /**
* Associate several instances with this * Associate several instances with this.
* *
* @param {Instance|String|Number} [newAssociation] An array of instances or primary key of instances to associate with this. Pass `null` or `undefined` to remove all associations. * @param {Instance|String|Number} [newAssociation] An array of instances or primary key of instances to associate with this. Pass `null` or `undefined` to remove all associations.
* @param {Object} [options] Options passed to `through.findAll`, `bulkCreate` and `update`. Can also hold additional attributes for the join table * @param {Object} [options] Options passed to `through.findAll`, `bulkCreate` and `update`. Can also hold additional attributes for the join table
...@@ -244,7 +246,7 @@ var BelongsToMany = function(source, target, options) { ...@@ -244,7 +246,7 @@ var BelongsToMany = function(source, target, options) {
*/ */
create: 'create' + singular, create: 'create' + singular,
/** /**
* Un-associate the instance * Un-associate the instance.
* *
* @param {Instace|String|Number} [oldAssociated] Can be an Instance or its primary key * @param {Instace|String|Number} [oldAssociated] Can be an Instance or its primary key
* @param {Object} [options] Options passed to `through.destroy` * @param {Object} [options] Options passed to `through.destroy`
...@@ -253,9 +255,9 @@ var BelongsToMany = function(source, target, options) { ...@@ -253,9 +255,9 @@ var BelongsToMany = function(source, target, options) {
*/ */
remove: 'remove' + singular, remove: 'remove' + singular,
/** /**
* Un-associate several instances * Un-associate several instances.
* *
* @param {Array<Instace|String|Number>} [oldAssociated] Can be an Instance or its primary key * @param {Array<Instace|String|Number>} [oldAssociated] Can be an array of instances or their primary keys
* @param {Object} [options] Options passed to `through.destroy` * @param {Object} [options] Options passed to `through.destroy`
* @return {Promise} * @return {Promise}
* @method removeAssociations * @method removeAssociations
...@@ -273,14 +275,14 @@ var BelongsToMany = function(source, target, options) { ...@@ -273,14 +275,14 @@ var BelongsToMany = function(source, target, options) {
/** /**
* Check if all instances are associated with this. * Check if all instances are associated with this.
* *
* @param {Array<Instace|String|Number>} [instances] Can be an Instance or its primary key * @param {Array<Instace|String|Number>} [instances] Can be an array of instances or their primary keys
* @param {Object} [options] Options passed to getAssociations * @param {Object} [options] Options passed to getAssociations
* @return {Promise} * @return {Promise}
* @method hasAssociations * @method hasAssociations
*/ */
hasAll: 'has' + plural, hasAll: 'has' + plural,
/** /**
* Count everything currently associated with this, using an optional where clause * Count everything currently associated with this, using an optional where clause.
* *
* @param {Object} [options] * @param {Object} [options]
* @param {Object} [options.where] An optional where clause to limit the associated models * @param {Object} [options.where] An optional where clause to limit the associated models
......
...@@ -72,7 +72,7 @@ var BelongsTo = function(source, target, options) { ...@@ -72,7 +72,7 @@ var BelongsTo = function(source, target, options) {
this.accessors = { this.accessors = {
/** /**
* Get the associated instance * Get the associated instance.
* *
* @param {Object} [options] * @param {Object} [options]
* @param {String|Boolean} [options.scope] Apply a scope on the related model, or remove its default scope by passing false. * @param {String|Boolean} [options.scope] Apply a scope on the related model, or remove its default scope by passing false.
...@@ -81,7 +81,7 @@ var BelongsTo = function(source, target, options) { ...@@ -81,7 +81,7 @@ var BelongsTo = function(source, target, options) {
*/ */
get: 'get' + singular, get: 'get' + singular,
/** /**
* Set the associated model * Set the associated model.
* *
* @param {Instance|String|Number} [newAssociation] An instance or the primary key of an instance to associate with this. Pass `null` or `undefined` to remove the association. * @param {Instance|String|Number} [newAssociation] An instance or the primary key of an instance to associate with this. Pass `null` or `undefined` to remove the association.
* @param {Object} [options] Options passed to `this.save` * @param {Object} [options] Options passed to `this.save`
......
...@@ -10,7 +10,7 @@ var Utils = require('./../utils') ...@@ -10,7 +10,7 @@ var Utils = require('./../utils')
/** /**
* One-to-many association * One-to-many association
* *
* In the API reference below, replace `Assocation(s)` with the actual name of your association, e.g. for `User.belongsToMany(Project)` the getter will be `user.getProjects()`. * In the API reference below, replace `Assocation(s)` with the actual name of your association, e.g. for `User.hasMany(Project)` the getter will be `user.getProjects()`.
* *
* @mixin HasMany * @mixin HasMany
*/ */
...@@ -92,7 +92,7 @@ var HasMany = function(source, target, options) { ...@@ -92,7 +92,7 @@ var HasMany = function(source, target, options) {
this.accessors = { this.accessors = {
/** /**
* Get everything currently associated with this, using an optional where clause * Get everything currently associated with this, using an optional where clause.
* *
* @param {Object} [options] * @param {Object} [options]
* @param {Object} [options.where] An optional where clause to limit the associated models * @param {Object} [options.where] An optional where clause to limit the associated models
...@@ -112,7 +112,7 @@ var HasMany = function(source, target, options) { ...@@ -112,7 +112,7 @@ var HasMany = function(source, target, options) {
*/ */
set: 'set' + plural, set: 'set' + plural,
/** /**
* Associate several instances with this * Associate several instances with this.
* *
* @param {Array<Instance|String|Number>} [newAssociations] An array of instances or primary key of instances to associate with this. Pass `null` or `undefined` to remove all associations. * @param {Array<Instance|String|Number>} [newAssociations] An array of instances or primary key of instances to associate with this. Pass `null` or `undefined` to remove all associations.
* @param {Object} [options] Options passed to `target.update`. * @param {Object} [options] Options passed to `target.update`.
...@@ -122,7 +122,7 @@ var HasMany = function(source, target, options) { ...@@ -122,7 +122,7 @@ var HasMany = function(source, target, options) {
*/ */
addMultiple: 'add' + plural, addMultiple: 'add' + plural,
/** /**
* Associate several instances with this * Associate several instances with this.
* *
* @param {Instance|String|Number} [newAssociation] An array of instances or primary key of instances to associate with this. Pass `null` or `undefined` to remove all associations. * @param {Instance|String|Number} [newAssociation] An array of instances or primary key of instances to associate with this. Pass `null` or `undefined` to remove all associations.
* @param {Object} [options] Options passed to `target.update`. * @param {Object} [options] Options passed to `target.update`.
...@@ -141,7 +141,7 @@ var HasMany = function(source, target, options) { ...@@ -141,7 +141,7 @@ var HasMany = function(source, target, options) {
*/ */
create: 'create' + singular, create: 'create' + singular,
/** /**
* Un-associate the instance * Un-associate the instance.
* *
* @param {Instace|String|Number} [oldAssociated] Can be an Instance or its primary key * @param {Instace|String|Number} [oldAssociated] Can be an Instance or its primary key
* @param {Object} [options] Options passed to `target.update` * @param {Object} [options] Options passed to `target.update`
...@@ -150,9 +150,9 @@ var HasMany = function(source, target, options) { ...@@ -150,9 +150,9 @@ var HasMany = function(source, target, options) {
*/ */
remove: 'remove' + singular, remove: 'remove' + singular,
/** /**
* Un-associate several instances * Un-associate several instances.
* *
* @param {Array<Instace|String|Number>} [oldAssociated] Can be an Instance or its primary key * @param {Array<Instace|String|Number>} [oldAssociatedArray] Can be an array of instances or their primary keys
* @param {Object} [options] Options passed to `through.destroy` * @param {Object} [options] Options passed to `through.destroy`
* @return {Promise} * @return {Promise}
* @method removeAssociations * @method removeAssociations
...@@ -170,14 +170,14 @@ var HasMany = function(source, target, options) { ...@@ -170,14 +170,14 @@ var HasMany = function(source, target, options) {
/** /**
* Check if all instances are associated with this. * Check if all instances are associated with this.
* *
* @param {Array<Instace|String|Number>} [instances] Can be an Instance or its primary key * @param {Array<Instace|String|Number>} [instances] Can be an array of instances or their primary keys
* @param {Object} [options] Options passed to getAssociations * @param {Object} [options] Options passed to getAssociations
* @return {Promise} * @return {Promise}
* @method hasAssociations * @method hasAssociations
*/ */
hasAll: 'has' + plural, hasAll: 'has' + plural,
/** /**
* Count everything currently associated with this, using an optional where clause * Count everything currently associated with this, using an optional where clause.
* *
* @param {Object} [options] * @param {Object} [options]
* @param {Object} [options.where] An optional where clause to limit the associated models * @param {Object} [options.where] An optional where clause to limit the associated models
......
...@@ -9,7 +9,8 @@ var Utils = require('./../utils') ...@@ -9,7 +9,8 @@ var Utils = require('./../utils')
/** /**
* One-to-one association * One-to-one association
* *
* In the API reference below, replace `Assocation(s)` with the actual name of your association, e.g. for `User.belongsToMany(Project)` the getter will be `user.getProjects()`. * In the API reference below, replace `Assocation` with the actual name of your association, e.g. for `User.hasOne(Project)` the getter will be `user.getProject()`.
* This is almost the same as `belongsTo` with one exception. The foreign key will be defined on the target model.
* *
* @mixin HasOne * @mixin HasOne
*/ */
...@@ -65,7 +66,7 @@ var HasOne = function(srcModel, targetModel, options) { ...@@ -65,7 +66,7 @@ var HasOne = function(srcModel, targetModel, options) {
this.accessors = { this.accessors = {
/** /**
* Get the associated instance * Get the associated instance.
* *
* @param {Object} [options] * @param {Object} [options]
* @param {String|Boolean} [options.scope] Apply a scope on the related model, or remove its default scope by passing false * @param {String|Boolean} [options.scope] Apply a scope on the related model, or remove its default scope by passing false
...@@ -74,9 +75,9 @@ var HasOne = function(srcModel, targetModel, options) { ...@@ -74,9 +75,9 @@ var HasOne = function(srcModel, targetModel, options) {
*/ */
get: 'get' + singular, get: 'get' + singular,
/** /**
* Set the associated model * Set the associated model.
* *
* @param {Instance|String|Number} [newAssociations] An array of instances or primary key of instances to associate with this. Pass `null` or `undefined` to remove all associations. * @param {Instance|String|Number} [newAssociation] An instance or the primary key of an instance to associate with this. Pass `null` or `undefined` to remove the association.
* @param {Object} [options] Options passed to getAssocation and `target.save` * @param {Object} [options] Options passed to getAssocation and `target.save`
* @return {Promise} * @return {Promise}
* @method setAssociation * @method setAssociation
......
...@@ -8,11 +8,12 @@ var Utils = require('./../utils') ...@@ -8,11 +8,12 @@ var Utils = require('./../utils')
, BelongsTo = require('./belongs-to'); , BelongsTo = require('./belongs-to');
/** /**
* Creating assocations in sequelize is done by calling one of the belongsTo / hasOne / hasMany functions on a model (the source), and providing another model as the first argument to the function (the target). * Creating assocations in sequelize is done by calling one of the belongsTo / hasOne / hasMany / belongsToMany functions on a model (the source), and providing another model as the first argument to the function (the target).
* *
* * hasOne - adds a foreign key to target * * hasOne - adds a foreign key to the target and singular association mixins to the source.
* * belongsTo - add a foreign key to source * * belongsTo - add a foreign key and singular association mixins to the source.
* * hasMany - adds a foreign key to target, unless you also specify that target hasMany source, in which case a junction table is created with sourceId and targetId * * hasMany - adds a foreign key to target and plural association mixins to the source.
* * belongsToMany - creates an N:M association with a join table and adds plural association mixins to the source. The junction table is created with sourceId and targetId.
* *
* Creating an association will add a foreign key constraint to the attributes. All associations use `CASCADE` on update and `SET NULL` on delete, except for n:m, which also uses `CASCADE` on delete. * Creating an association will add a foreign key constraint to the attributes. All associations use `CASCADE` on update and `SET NULL` on delete, except for n:m, which also uses `CASCADE` on delete.
* *
...@@ -148,54 +149,15 @@ Mixin.hasOne = singleLinked(HasOne); ...@@ -148,54 +149,15 @@ Mixin.hasOne = singleLinked(HasOne);
Mixin.belongsTo = singleLinked(BelongsTo); Mixin.belongsTo = singleLinked(BelongsTo);
/** /**
* Create an association that is either 1:m or n:m. * Creates a 1:m association between this (the source) and the provided target. The foreign key is added on the target.
* *
* ```js * Example: `User.hasMany(Profile)`. This will add userId to the profile table.
* // Create a 1:m association between user and project
* User.hasMany(Project)
* ```
* ```js
* // Create a n:m association between user and project
* User.hasMany(Project)
* Project.hasMany(User)
* ```
* By default, the name of the join table will be source+target, so in this case projectsusers. This can be overridden by providing either a string or a Model as `through` in the options.
* If you use a through model with custom attributes, these attributes can be set when adding / setting new associations in two ways. Consider users and projects from before with a join table that stores whether the project has been started yet:
* ```js
* var UserProjects = sequelize.define('userprojects', {
* started: Sequelize.BOOLEAN
* })
* User.hasMany(Project, { through: UserProjects })
* Project.hasMany(User, { through: UserProjects })
* ```
* ```js
* jan.addProject(homework, { started: false }) // The homework project is not started yet
* jan.setProjects([makedinner, doshopping], { started: true}) // Both shopping and dinner have been started
* ```
*
* If you want to set several target instances, but with different attributes you have to set the attributes on the instance, using a property with the name of the through model:
*
* ```js
* p1.userprojects {
* started: true
* }
* user.setProjects([p1, p2], {started: false}) // The default value is false, but p1 overrides that.
* ```
*
* Similarily, when fetching through a join table with custom attributes, these attributes will be available as an object with the name of the through model.
* ```js
* user.getProjects().then(function (projects) {
* var p1 = projects[0]
* p1.userprojects.started // Is this project started yet?
* })
* ```
* *
* @param {Model} target * @param {Model} target
* @param {object} [options] * @param {object} [options]
* @param {boolean} [options.hooks=false] Set to true to run before-/afterDestroy hooks when an associated model is deleted because of a cascade. For example if `User.hasOne(Profile, {onDelete: 'cascade', hooks:true})`, the before-/afterDestroy hooks for profile will be called when a user is deleted. Otherwise the profile will be deleted without invoking any hooks * @param {boolean} [options.hooks=false] Set to true to run before-/afterDestroy hooks when an associated model is deleted because of a cascade. For example if `User.hasOne(Profile, {onDelete: 'cascade', hooks:true})`, the before-/afterDestroy hooks for profile will be called when a user is deleted. Otherwise the profile will be deleted without invoking any hooks
* @param {string|object} [options.as] The alias of this model. If you provide a string, it should be plural, and will be singularized using node.inflection. If you want to control the singular version yourself, provide an object with `plural` and `singular` keys. See also the `name` option passed to `sequelize.define`. If you create multiple associations between the same tables, you should provide an alias to be able to distinguish between them. If you provide an alias when creating the assocition, you should provide the same alias when eager loading and when getting assocated models. Defaults to the pluralized name of target * @param {string|object} [options.as] The alias of this model. If you provide a string, it should be plural, and will be singularized using node.inflection. If you want to control the singular version yourself, provide an object with `plural` and `singular` keys. See also the `name` option passed to `sequelize.define`. If you create multiple associations between the same tables, you should provide an alias to be able to distinguish between them. If you provide an alias when creating the assocition, you should provide the same alias when eager loading and when getting assocated models. Defaults to the pluralized name of target
* @param {string|object} [options.foreignKey] The name of the foreign key in the target table / join table or an object representing the type definition for the foreign column (see `Sequelize.define` for syntax). When using an object, you can add a `name` property to set the name of the colum. Defaults to the name of source + primary key of source * @param {string|object} [options.foreignKey] The name of the foreign key in the target table or an object representing the type definition for the foreign column (see `Sequelize.define` for syntax). When using an object, you can add a `name` property to set the name of the column. Defaults to the name of source + primary key of source
* @param {object} [options.scope] A key/value set that will be used for association create and find defaults on the target. (sqlite not supported for N:M) * @param {object} [options.scope] A key/value set that will be used for association create and find defaults on the target. (sqlite not supported for N:M)
* @param {string} [options.onDelete='SET&nbsp;NULL|CASCADE'] SET NULL if foreignKey allows nulls, CASCADE if otherwise * @param {string} [options.onDelete='SET&nbsp;NULL|CASCADE'] SET NULL if foreignKey allows nulls, CASCADE if otherwise
* @param {string} [options.onUpdate='CASCADE'] * @param {string} [options.onUpdate='CASCADE']
...@@ -226,17 +188,17 @@ Mixin.hasMany = function(target, options) { // testhint options:none ...@@ -226,17 +188,17 @@ Mixin.hasMany = function(target, options) { // testhint options:none
}; };
/** /**
* Create an N:M association with a join table * Create an N:M association with a join table.
* *
* ```js * ```js
* User.belongsToMany(Project) * User.belongsToMany(Project, { through: 'UserProjects' })
* Project.belongsToMany(User) * Project.belongsToMany(User, { through: 'UserProjects' })
* ``` * ```
* By default, the name of the join table will be source+target, so in this case projectsusers. This can be overridden by providing either a string or a Model as `through` in the options. * Defining `through` is required. Sequelize would previously attempt to auto generate names but that would not always lead to the most logical setups.
* *
* If you use a through model with custom attributes, these attributes can be set when adding / setting new associations in two ways. Consider users and projects from before with a join table that stores whether the project has been started yet: * If you define a through model with custom attributes, these attributes can be set when adding / setting new associations in two ways. Consider users and projects from before with a join table that stores whether the project has been started yet:
* ```js * ```js
* var UserProjects = sequelize.define('userprojects', { * var UserProjects = sequelize.define('UserProjects', {
* started: Sequelize.BOOLEAN * started: Sequelize.BOOLEAN
* }) * })
* User.belongsToMany(Project, { through: UserProjects }) * User.belongsToMany(Project, { through: UserProjects })
...@@ -250,7 +212,7 @@ Mixin.hasMany = function(target, options) { // testhint options:none ...@@ -250,7 +212,7 @@ Mixin.hasMany = function(target, options) { // testhint options:none
* If you want to set several target instances, but with different attributes you have to set the attributes on the instance, using a property with the name of the through model: * If you want to set several target instances, but with different attributes you have to set the attributes on the instance, using a property with the name of the through model:
* *
* ```js * ```js
* p1.userprojects { * p1.UserProjects = {
* started: true * started: true
* } * }
* user.setProjects([p1, p2], {started: false}) // The default value is false, but p1 overrides that. * user.setProjects([p1, p2], {started: false}) // The default value is false, but p1 overrides that.
...@@ -260,7 +222,7 @@ Mixin.hasMany = function(target, options) { // testhint options:none ...@@ -260,7 +222,7 @@ Mixin.hasMany = function(target, options) { // testhint options:none
* ```js * ```js
* user.getProjects().then(function (projects) { * user.getProjects().then(function (projects) {
* var p1 = projects[0] * var p1 = projects[0]
* p1.userprojects.started // Is this project started yet? * p1.UserProjects.started // Is this project started yet?
* }) * })
* ``` * ```
* *
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!