2019-05-08 15:45:37 +00:00
|
|
|
|
// Copyright IBM Corp. 2013,2018. All Rights Reserved.
|
2016-04-01 22:25:16 +00:00
|
|
|
|
// Node module: loopback-datasource-juggler
|
|
|
|
|
// This file is licensed under the MIT License.
|
|
|
|
|
// License text available at https://opensource.org/licenses/MIT
|
2019-05-08 15:45:37 +00:00
|
|
|
|
|
2016-08-22 19:55:22 +00:00
|
|
|
|
'use strict';
|
2016-04-01 22:25:16 +00:00
|
|
|
|
|
2014-03-12 23:28:46 +00:00
|
|
|
|
/*!
|
2013-04-11 23:23:34 +00:00
|
|
|
|
* Dependencies
|
|
|
|
|
*/
|
2018-12-07 14:54:29 +00:00
|
|
|
|
const relation = require('./relation-definition');
|
|
|
|
|
const RelationDefinition = relation.RelationDefinition;
|
2013-04-11 23:23:34 +00:00
|
|
|
|
|
2014-06-15 22:53:58 +00:00
|
|
|
|
module.exports = RelationMixin;
|
2013-06-05 21:33:52 +00:00
|
|
|
|
|
2014-03-12 23:28:46 +00:00
|
|
|
|
/**
|
2017-06-01 15:00:44 +00:00
|
|
|
|
* RelationMixin class. Use to define relationships between models.
|
2014-03-12 23:28:46 +00:00
|
|
|
|
*
|
2014-06-15 22:53:58 +00:00
|
|
|
|
* @class RelationMixin
|
2014-03-12 23:28:46 +00:00
|
|
|
|
*/
|
2014-06-15 22:53:58 +00:00
|
|
|
|
function RelationMixin() {
|
2014-01-29 02:00:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
2013-04-11 23:23:34 +00:00
|
|
|
|
/**
|
2017-06-01 15:00:44 +00:00
|
|
|
|
* Define a "one to many" relationship by specifying the model name.
|
2016-04-01 11:48:17 +00:00
|
|
|
|
*
|
2014-05-16 00:59:23 +00:00
|
|
|
|
* Examples:
|
|
|
|
|
* ```
|
|
|
|
|
* User.hasMany(Post, {as: 'posts', foreignKey: 'authorId'});
|
|
|
|
|
* ```
|
2016-04-01 11:48:17 +00:00
|
|
|
|
*
|
2014-05-16 00:59:23 +00:00
|
|
|
|
* ```
|
|
|
|
|
* Book.hasMany(Chapter);
|
|
|
|
|
* ```
|
|
|
|
|
* Or, equivalently:
|
|
|
|
|
* ```
|
|
|
|
|
* Book.hasMany('chapters', {model: Chapter});
|
|
|
|
|
* ```
|
2014-05-22 00:50:44 +00:00
|
|
|
|
*
|
|
|
|
|
* Query and create related models:
|
|
|
|
|
*
|
|
|
|
|
* ```js
|
|
|
|
|
* Book.create(function(err, book) {
|
2016-04-01 11:48:17 +00:00
|
|
|
|
*
|
2014-05-22 00:50:44 +00:00
|
|
|
|
* // Create a chapter instance ready to be saved in the data source.
|
|
|
|
|
* var chapter = book.chapters.build({name: 'Chapter 1'});
|
2016-04-01 11:48:17 +00:00
|
|
|
|
*
|
2014-05-22 00:50:44 +00:00
|
|
|
|
* // Save the new chapter
|
|
|
|
|
* chapter.save();
|
2016-04-01 11:48:17 +00:00
|
|
|
|
*
|
2014-05-22 00:50:44 +00:00
|
|
|
|
* // you can also call the Chapter.create method with the `chapters` property which will build a chapter
|
|
|
|
|
* // instance and save the it in the data source.
|
|
|
|
|
* book.chapters.create({name: 'Chapter 2'}, function(err, savedChapter) {
|
2017-06-01 15:00:44 +00:00
|
|
|
|
* // this callback is optional
|
2014-05-22 00:50:44 +00:00
|
|
|
|
* });
|
2016-04-01 11:48:17 +00:00
|
|
|
|
*
|
|
|
|
|
* // Query chapters for the book
|
2017-06-01 15:00:44 +00:00
|
|
|
|
* book.chapters(function(err, chapters) {
|
|
|
|
|
* // all chapters with bookId = book.id
|
2014-05-22 00:50:44 +00:00
|
|
|
|
* console.log(chapters);
|
|
|
|
|
* });
|
2016-04-01 11:48:17 +00:00
|
|
|
|
*
|
2017-06-01 15:00:44 +00:00
|
|
|
|
* // Query chapters for the book with a filter
|
2014-05-22 00:50:44 +00:00
|
|
|
|
* book.chapters({where: {name: 'test'}, function(err, chapters) {
|
|
|
|
|
* // All chapters with bookId = book.id and name = 'test'
|
|
|
|
|
* console.log(chapters);
|
|
|
|
|
* });
|
|
|
|
|
* });
|
2017-06-01 15:00:44 +00:00
|
|
|
|
* ```
|
|
|
|
|
*
|
2014-06-15 22:53:58 +00:00
|
|
|
|
* @param {Object|String} modelTo Model object (or String name of model) to which you are creating the relationship.
|
2017-06-01 15:00:44 +00:00
|
|
|
|
* @options {Object} params Configuration parameters; see below.
|
2014-05-22 22:02:57 +00:00
|
|
|
|
* @property {String} as Name of the property in the referring model that corresponds to the foreign key field in the related model.
|
2014-05-16 00:59:23 +00:00
|
|
|
|
* @property {String} foreignKey Property name of foreign key field.
|
2017-06-01 15:00:44 +00:00
|
|
|
|
* @property {String} polymorphic Define a polymorphic relation name.
|
|
|
|
|
* @property {String} through Name of the through model.
|
|
|
|
|
* @property {String} keyThrough Property name of the foreign key in the through model.
|
|
|
|
|
* @property {Object|Function} scope Explicitly define additional scopes.
|
|
|
|
|
* @property {Boolean} invert Specify if the relation is inverted.
|
|
|
|
|
* @property {Object} model The model object.
|
2013-04-11 23:23:34 +00:00
|
|
|
|
*/
|
2014-06-15 22:53:58 +00:00
|
|
|
|
RelationMixin.hasMany = function hasMany(modelTo, params) {
|
2014-08-13 09:28:23 +00:00
|
|
|
|
return RelationDefinition.hasMany(this, modelTo, params);
|
2013-04-11 23:23:34 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
2014-05-16 00:59:23 +00:00
|
|
|
|
* Declare "belongsTo" relation that sets up a one-to-one connection with another model, such that each
|
|
|
|
|
* instance of the declaring model "belongs to" one instance of the other model.
|
2013-04-11 23:23:34 +00:00
|
|
|
|
*
|
2014-05-16 00:59:23 +00:00
|
|
|
|
* For example, if an application includes users and posts, and each post can be written by exactly one user.
|
|
|
|
|
* The following code specifies that `Post` has a reference called `author` to the `User` model via the `userId` property of `Post`
|
|
|
|
|
* as the foreign key.
|
|
|
|
|
* ```
|
|
|
|
|
* Post.belongsTo(User, {as: 'author', foreignKey: 'userId'});
|
|
|
|
|
* ```
|
|
|
|
|
* You can then access the author in one of the following styles.
|
|
|
|
|
* Get the User object for the post author asynchronously:
|
|
|
|
|
* ```
|
|
|
|
|
* post.author(callback);
|
|
|
|
|
* ```
|
|
|
|
|
* Get the User object for the post author synchronously:
|
|
|
|
|
* ```
|
|
|
|
|
* post.author();
|
2015-12-28 15:03:37 +00:00
|
|
|
|
* ```
|
2014-05-16 00:59:23 +00:00
|
|
|
|
* Set the author to be the given user:
|
|
|
|
|
* ```
|
2016-04-01 11:48:17 +00:00
|
|
|
|
* post.author(user)
|
2014-05-16 00:59:23 +00:00
|
|
|
|
* ```
|
|
|
|
|
* Examples:
|
2016-04-01 11:48:17 +00:00
|
|
|
|
*
|
2014-03-12 23:28:46 +00:00
|
|
|
|
* Suppose the model Post has a *belongsTo* relationship with User (the author of the post). You could declare it this way:
|
|
|
|
|
* ```js
|
2013-04-11 23:23:34 +00:00
|
|
|
|
* Post.belongsTo(User, {as: 'author', foreignKey: 'userId'});
|
2014-03-12 23:28:46 +00:00
|
|
|
|
* ```
|
2013-04-11 23:23:34 +00:00
|
|
|
|
*
|
|
|
|
|
* When a post is loaded, you can load the related author with:
|
2014-03-12 23:28:46 +00:00
|
|
|
|
* ```js
|
2013-04-11 23:23:34 +00:00
|
|
|
|
* post.author(function(err, user) {
|
|
|
|
|
* // the user variable is your user object
|
|
|
|
|
* });
|
2014-03-12 23:28:46 +00:00
|
|
|
|
* ```
|
2013-04-11 23:23:34 +00:00
|
|
|
|
*
|
|
|
|
|
* The related object is cached, so if later you try to get again the author, no additional request will be made.
|
|
|
|
|
* But there is an optional boolean parameter in first position that set whether or not you want to reload the cache:
|
2014-03-12 23:28:46 +00:00
|
|
|
|
* ```js
|
2013-04-11 23:23:34 +00:00
|
|
|
|
* post.author(true, function(err, user) {
|
|
|
|
|
* // The user is reloaded, even if it was already cached.
|
|
|
|
|
* });
|
2014-03-12 23:28:46 +00:00
|
|
|
|
* ```
|
2013-04-11 23:23:34 +00:00
|
|
|
|
* This optional parameter default value is false, so the related object will be loaded from cache if available.
|
2014-06-21 06:02:37 +00:00
|
|
|
|
*
|
2014-06-15 22:53:58 +00:00
|
|
|
|
* @param {Class|String} modelTo Model object (or String name of model) to which you are creating the relationship.
|
2014-05-22 00:50:44 +00:00
|
|
|
|
* @options {Object} params Configuration parameters; see below.
|
2014-05-22 22:02:57 +00:00
|
|
|
|
* @property {String} as Name of the property in the referring model that corresponds to the foreign key field in the related model.
|
2017-06-01 15:00:44 +00:00
|
|
|
|
* @property {String} primaryKey Property name of primary key field.
|
2014-05-16 00:59:23 +00:00
|
|
|
|
* @property {String} foreignKey Name of foreign key property.
|
2017-06-01 15:00:44 +00:00
|
|
|
|
* @property {Object|Function} scope Explicitly define additional scopes.
|
|
|
|
|
* @property {Object} properties Properties inherited from the parent object.
|
|
|
|
|
* @property {Object} options Property level options.
|
|
|
|
|
* @property {Boolean} options.invertProperties Specify if the properties should be inverted.
|
2013-04-11 23:23:34 +00:00
|
|
|
|
*/
|
2016-04-01 11:48:17 +00:00
|
|
|
|
RelationMixin.belongsTo = function(modelTo, params) {
|
2014-08-13 09:28:23 +00:00
|
|
|
|
return RelationDefinition.belongsTo(this, modelTo, params);
|
2013-04-11 23:23:34 +00:00
|
|
|
|
};
|
|
|
|
|
|
2013-04-12 21:35:06 +00:00
|
|
|
|
/**
|
2014-05-16 00:59:23 +00:00
|
|
|
|
* A hasAndBelongsToMany relation creates a direct many-to-many connection with another model, with no intervening model.
|
2017-06-01 15:00:44 +00:00
|
|
|
|
*
|
2014-05-16 00:59:23 +00:00
|
|
|
|
* For example, if your application includes users and groups, with each group having many users and each user appearing
|
|
|
|
|
* in many groups, you could declare the models this way:
|
|
|
|
|
* ```
|
|
|
|
|
* User.hasAndBelongsToMany('groups', {model: Group, foreignKey: 'groupId'});
|
|
|
|
|
* ```
|
|
|
|
|
* Then, to get the groups to which the user belongs:
|
|
|
|
|
* ```
|
|
|
|
|
* user.groups(callback);
|
|
|
|
|
* ```
|
|
|
|
|
* Create a new group and connect it with the user:
|
|
|
|
|
* ```
|
|
|
|
|
* user.groups.create(data, callback);
|
|
|
|
|
* ```
|
|
|
|
|
* Connect an existing group with the user:
|
|
|
|
|
* ```
|
|
|
|
|
* user.groups.add(group, callback);
|
|
|
|
|
* ```
|
|
|
|
|
* Remove the user from the group:
|
|
|
|
|
* ```
|
2016-04-01 11:48:17 +00:00
|
|
|
|
* user.groups.remove(group, callback);
|
2014-05-16 00:59:23 +00:00
|
|
|
|
* ```
|
2016-04-01 11:48:17 +00:00
|
|
|
|
*
|
2014-06-15 22:53:58 +00:00
|
|
|
|
* @param {String|Object} modelTo Model object (or String name of model) to which you are creating the relationship.
|
2014-05-22 00:50:44 +00:00
|
|
|
|
* @options {Object} params Configuration parameters; see below.
|
2014-05-22 22:02:57 +00:00
|
|
|
|
* @property {String} as Name of the property in the referring model that corresponds to the foreign key field in the related model.
|
2014-05-16 00:59:23 +00:00
|
|
|
|
* @property {String} foreignKey Property name of foreign key field.
|
2017-06-01 15:00:44 +00:00
|
|
|
|
* @property {String} throughTable The table name of the through model.
|
|
|
|
|
* @property {String} through Name of the through model.
|
|
|
|
|
* @property {String} polymorphic Define a polymorphic relation name.
|
|
|
|
|
* @property {Object|Function} scope Explicitly define additional scopes.
|
|
|
|
|
* @property {Object} model The model object.
|
2013-04-12 21:35:06 +00:00
|
|
|
|
*/
|
2014-06-15 22:53:58 +00:00
|
|
|
|
RelationMixin.hasAndBelongsToMany = function hasAndBelongsToMany(modelTo, params) {
|
2014-08-13 09:28:23 +00:00
|
|
|
|
return RelationDefinition.hasAndBelongsToMany(this, modelTo, params);
|
2013-04-12 21:35:06 +00:00
|
|
|
|
};
|
2014-01-24 17:09:53 +00:00
|
|
|
|
|
2017-06-01 15:00:44 +00:00
|
|
|
|
/**
|
|
|
|
|
* Define a "one to one" relationship by specifying the model name.
|
|
|
|
|
*
|
|
|
|
|
* Examples:
|
|
|
|
|
* ```
|
|
|
|
|
* Supplier.hasOne(Account, {as: 'account', foreignKey: 'supplierId'});
|
|
|
|
|
* ```
|
|
|
|
|
*
|
|
|
|
|
* If the target model doesn’t have a foreign key property, LoopBack will add a property with the same name.
|
|
|
|
|
*
|
|
|
|
|
* The type of the property will be the same as the type of the target model’s id property.
|
|
|
|
|
*
|
|
|
|
|
* Please note the foreign key property is defined on the target model (in this example, Account).
|
|
|
|
|
*
|
|
|
|
|
* If you don’t specify them, then LoopBack derives the relation name and foreign key as follows:
|
|
|
|
|
* - Relation name: Camel case of the model name, for example, for the “supplier” model the relation is “supplier”.
|
|
|
|
|
* - Foreign key: The relation name appended with Id, for example, for relation name “supplier” the default foreign key is “supplierId”.
|
|
|
|
|
*
|
|
|
|
|
* Build a new account for the supplier with the supplierId to be set to the id of the supplier.
|
|
|
|
|
* ```js
|
|
|
|
|
* var supplier = supplier.account.build(data);
|
|
|
|
|
* ```
|
|
|
|
|
*
|
|
|
|
|
* Create a new account for the supplier. If there is already an account, an error will be reported.
|
|
|
|
|
* ```js
|
|
|
|
|
* supplier.account.create(data, function(err, account) {
|
|
|
|
|
* ...
|
|
|
|
|
* });
|
|
|
|
|
* ```
|
|
|
|
|
*
|
|
|
|
|
* Find the supplier's account model.
|
|
|
|
|
* ```js
|
|
|
|
|
* supplier.account(function(err, account) {
|
|
|
|
|
* ...
|
|
|
|
|
* });
|
|
|
|
|
* ```
|
|
|
|
|
*
|
|
|
|
|
* Update the associated account.
|
|
|
|
|
* ```js
|
|
|
|
|
* supplier.account.update({balance: 100}, function(err, account) {
|
|
|
|
|
* ...
|
|
|
|
|
* });
|
|
|
|
|
* ```
|
|
|
|
|
*
|
|
|
|
|
* Remove the account for the supplier.
|
|
|
|
|
* ```js
|
|
|
|
|
* supplier.account.destroy(function(err) {
|
|
|
|
|
* ...
|
|
|
|
|
* });
|
|
|
|
|
* ```
|
|
|
|
|
*
|
|
|
|
|
* @param {Object|String} modelTo Model object (or String name of model) to which you are creating the relationship.
|
|
|
|
|
* @options {Object} params Configuration parameters; see below.
|
|
|
|
|
* @property {String} as Name of the property in the referring model that corresponds to the foreign key field in the related model.
|
|
|
|
|
* @property {String} primaryKey Property name of primary key field.
|
|
|
|
|
* @property {String} foreignKey Property name of foreign key field.
|
|
|
|
|
* @property {String} polymorphic Define a polymorphic relation name.
|
|
|
|
|
* @property {Object|Function} scope Explicitly define additional scopes.
|
|
|
|
|
* @property {Object} model The model object.
|
|
|
|
|
* @property {Object} properties Properties inherited from the parent object.
|
|
|
|
|
* @property {Function} methods Scoped methods for the given relation.
|
|
|
|
|
*/
|
2014-08-19 20:10:35 +00:00
|
|
|
|
RelationMixin.hasOne = function hasOne(modelTo, params) {
|
2014-08-13 09:28:23 +00:00
|
|
|
|
return RelationDefinition.hasOne(this, modelTo, params);
|
2013-04-12 21:35:06 +00:00
|
|
|
|
};
|
2014-07-27 14:30:45 +00:00
|
|
|
|
|
2017-06-01 15:00:44 +00:00
|
|
|
|
/**
|
|
|
|
|
* References one or more instances of the target model.
|
|
|
|
|
*
|
|
|
|
|
* For example, a Customer model references one or more instances of the Account model.
|
|
|
|
|
*
|
|
|
|
|
* Define the relation in the model definition:
|
|
|
|
|
*
|
|
|
|
|
* - Definition of Customer model:
|
|
|
|
|
* ```json
|
|
|
|
|
* {
|
|
|
|
|
"name": "Customer",
|
|
|
|
|
"base": "PersistedModel",
|
|
|
|
|
"idInjection": true,
|
|
|
|
|
"properties": {
|
|
|
|
|
"name": {
|
|
|
|
|
"type": "string"
|
|
|
|
|
},
|
|
|
|
|
"age": {
|
|
|
|
|
"type": "number"
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
"validations": [],
|
|
|
|
|
"relations": {
|
|
|
|
|
"accounts": {
|
|
|
|
|
"type": "referencesMany",
|
|
|
|
|
"model": "Account",
|
|
|
|
|
"foreignKey": "accountIds",
|
|
|
|
|
"options": {
|
|
|
|
|
"validate": true,
|
|
|
|
|
"forceId": false
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
"acls": [],
|
|
|
|
|
"methods": {}
|
|
|
|
|
}
|
|
|
|
|
* ```
|
|
|
|
|
*
|
|
|
|
|
* - Definition of Account model:
|
|
|
|
|
* ```json
|
|
|
|
|
* {
|
|
|
|
|
"name": "Account",
|
|
|
|
|
"base": "PersistedModel",
|
|
|
|
|
"idInjection": true,
|
|
|
|
|
"properties": {
|
|
|
|
|
"name": {
|
|
|
|
|
"type": "string"
|
|
|
|
|
},
|
|
|
|
|
"balance": {
|
|
|
|
|
"type": "number"
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
"validations": [],
|
|
|
|
|
"relations": {},
|
|
|
|
|
"acls": [],
|
|
|
|
|
"methods": {}
|
|
|
|
|
}
|
|
|
|
|
* ```
|
|
|
|
|
*
|
|
|
|
|
* On the bootscript, create a customer instance and for that customer instance reference many account instances.
|
|
|
|
|
*
|
|
|
|
|
* For example:
|
|
|
|
|
* ```javascript
|
|
|
|
|
* var Customer = app.models.Customer;
|
|
|
|
|
var accounts = [
|
|
|
|
|
{
|
|
|
|
|
name: 'Checking',
|
|
|
|
|
balance: 5000
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: 'Saving',
|
|
|
|
|
balance: 2000
|
|
|
|
|
}
|
|
|
|
|
];
|
|
|
|
|
Customer.create({name: 'Mary Smith'}, function(err, customer) {
|
|
|
|
|
console.log('Customer:', customer);
|
|
|
|
|
async.each(accounts, function(account, done) {
|
|
|
|
|
customer.accounts.create(account, done);
|
|
|
|
|
}, function(err) {
|
|
|
|
|
console.log('Customer with accounts:', customer);
|
|
|
|
|
customer.accounts(console.log);
|
|
|
|
|
cb(err);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
* ```
|
|
|
|
|
*
|
|
|
|
|
* Sample referencesMany model data:
|
|
|
|
|
* ```javascript
|
|
|
|
|
* {
|
|
|
|
|
id: 1,
|
|
|
|
|
name: 'John Smith',
|
|
|
|
|
accounts: [
|
|
|
|
|
"saving-01", "checking-01",
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
* ```
|
|
|
|
|
*
|
|
|
|
|
* Supported helper methods:
|
|
|
|
|
* - customer.accounts()
|
|
|
|
|
* - customer.accounts.create()
|
|
|
|
|
* - customer.accounts.build()
|
|
|
|
|
* - customer.accounts.findById()
|
|
|
|
|
* - customer.accounts.destroy()
|
|
|
|
|
* - customer.accounts.updateById()
|
|
|
|
|
* - customer.accounts.exists()
|
|
|
|
|
* - customer.accounts.add()
|
|
|
|
|
* - customer.accounts.remove()
|
|
|
|
|
* - customer.accounts.at()
|
|
|
|
|
*
|
|
|
|
|
* @param {Object|String} modelTo Model object (or String name of model) to which you are creating the relationship.
|
|
|
|
|
* @options {Object} params Configuration parameters; see below.
|
|
|
|
|
* @property {String} as Name of the property in the referring model that corresponds to the foreign key field in the related model.
|
|
|
|
|
* @property {Any} default The default value.
|
|
|
|
|
* @property {Object} options Options to specify for the relationship.
|
|
|
|
|
* @property {Boolean} options.forceId Force generation of id for embedded items. Default is false.
|
|
|
|
|
* @property {Boolean} options.validate Denote if the embedded items should be validated. Default is true.
|
|
|
|
|
* @property {Boolean} options.persistent Denote if the embedded items should be persisted. Default is false.
|
|
|
|
|
* @property {Object|Function} scope Explicitly define additional scopes.
|
|
|
|
|
* @property {String} foreignKey Property name of foreign key field.
|
|
|
|
|
* @property {Object} properties Properties inherited from the parent object.
|
|
|
|
|
* @property {Function} methods Scoped methods for the given relation.
|
|
|
|
|
*/
|
2014-08-19 20:10:35 +00:00
|
|
|
|
RelationMixin.referencesMany = function referencesMany(modelTo, params) {
|
2014-08-13 09:28:23 +00:00
|
|
|
|
return RelationDefinition.referencesMany(this, modelTo, params);
|
2014-07-29 08:51:33 +00:00
|
|
|
|
};
|
|
|
|
|
|
2017-06-01 15:00:44 +00:00
|
|
|
|
/**
|
|
|
|
|
* Represent a model that embeds another model.
|
|
|
|
|
*
|
|
|
|
|
* For example, a Customer embeds one billingAddress from the Address model.
|
|
|
|
|
*
|
|
|
|
|
* - Define the relation in bootscript:
|
|
|
|
|
* ```js
|
|
|
|
|
* Customer.embedsOne(Address, {
|
|
|
|
|
* as: 'address', // default to the relation name - address
|
|
|
|
|
* property: 'billingAddress' // default to addressItem
|
|
|
|
|
* });
|
|
|
|
|
* ```
|
|
|
|
|
*
|
|
|
|
|
* OR, define the relation in the model definition:
|
|
|
|
|
*
|
|
|
|
|
* - Definition of Customer model:
|
|
|
|
|
* ```json
|
|
|
|
|
* {
|
|
|
|
|
"name": "Customer",
|
|
|
|
|
"base": "PersistedModel",
|
|
|
|
|
"idInjection": true,
|
|
|
|
|
"properties": {
|
|
|
|
|
"name": {
|
|
|
|
|
"type": "string"
|
|
|
|
|
},
|
|
|
|
|
"age": {
|
|
|
|
|
"type": "number"
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
"validations": [],
|
|
|
|
|
"relations": {
|
|
|
|
|
"address": {
|
|
|
|
|
"type": "embedsOne",
|
|
|
|
|
"model": "Address",
|
|
|
|
|
"property": "billingAddress",
|
|
|
|
|
"options": {
|
|
|
|
|
"validate": true,
|
|
|
|
|
"forceId": false
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
"acls": [],
|
|
|
|
|
"methods": {}
|
|
|
|
|
}
|
|
|
|
|
* ```
|
|
|
|
|
*
|
|
|
|
|
* - Definition of Address model:
|
|
|
|
|
* ```json
|
|
|
|
|
* {
|
|
|
|
|
"name": "Address",
|
|
|
|
|
"base": "Model",
|
|
|
|
|
"idInjection": true,
|
|
|
|
|
"properties": {
|
|
|
|
|
"street": {
|
|
|
|
|
"type": "string"
|
|
|
|
|
},
|
|
|
|
|
"city": {
|
|
|
|
|
"type": "string"
|
|
|
|
|
},
|
|
|
|
|
"state": {
|
|
|
|
|
"type": "string"
|
|
|
|
|
},
|
|
|
|
|
"zipCode": {
|
|
|
|
|
"type": "string"
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
"validations": [],
|
|
|
|
|
"relations": {},
|
|
|
|
|
"acls": [],
|
|
|
|
|
"methods": {}
|
|
|
|
|
}
|
|
|
|
|
* ```
|
|
|
|
|
*
|
|
|
|
|
* Sample embedded model data:
|
|
|
|
|
* ```javascript
|
|
|
|
|
* {
|
|
|
|
|
id: 1,
|
|
|
|
|
name: 'John Smith',
|
|
|
|
|
billingAddress: {
|
|
|
|
|
street: '123 Main St',
|
|
|
|
|
city: 'San Jose',
|
|
|
|
|
state: 'CA',
|
|
|
|
|
zipCode: '95124'
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
* ```
|
|
|
|
|
*
|
|
|
|
|
* Supported helper methods:
|
|
|
|
|
* - customer.address()
|
|
|
|
|
* - customer.address.build()
|
|
|
|
|
* - customer.address.create()
|
|
|
|
|
* - customer.address.update()
|
|
|
|
|
* - customer.address.destroy()
|
|
|
|
|
* - customer.address.value()
|
|
|
|
|
*
|
|
|
|
|
* @param {Object|String} modelTo Model object (or String name of model) to which you are creating the relationship.
|
|
|
|
|
* @options {Object} params Configuration parameters; see below.
|
|
|
|
|
* @property {String} as Name of the property in the referring model that corresponds to the foreign key field in the related model.
|
|
|
|
|
* @property {String} property Name of the property for the embedded item.
|
|
|
|
|
* @property {Any} default The default value.
|
|
|
|
|
* @property {Object} options Options to specify for the relationship.
|
|
|
|
|
* @property {Boolean} options.forceId Force generation of id for embedded items. Default is false.
|
|
|
|
|
* @property {Boolean} options.validate Denote if the embedded items should be validated. Default is true.
|
|
|
|
|
* @property {Boolean} options.persistent Denote if the embedded items should be persisted. Default is false.
|
|
|
|
|
* @property {Object|Function} scope Explicitly define additional scopes.
|
|
|
|
|
* @property {Object} properties Properties inherited from the parent object.
|
|
|
|
|
* @property {Function} methods Scoped methods for the given relation.
|
|
|
|
|
*/
|
2014-08-19 20:10:35 +00:00
|
|
|
|
RelationMixin.embedsOne = function embedsOne(modelTo, params) {
|
|
|
|
|
return RelationDefinition.embedsOne(this, modelTo, params);
|
|
|
|
|
};
|
|
|
|
|
|
2017-06-01 15:00:44 +00:00
|
|
|
|
/**
|
|
|
|
|
* Represent a model that can embed many instances of another model.
|
|
|
|
|
*
|
|
|
|
|
* For example, a Customer can have multiple email addresses and each email address is a complex object that contains label and address.
|
|
|
|
|
*
|
|
|
|
|
* Define the relation code in bootscript:
|
|
|
|
|
* ```javascript
|
|
|
|
|
Customer.embedsMany(EmailAddress, {
|
|
|
|
|
as: 'emails', // default to the relation name - emailAddresses
|
|
|
|
|
property: 'emailList' // default to emailAddressItems
|
|
|
|
|
});
|
|
|
|
|
* ```
|
|
|
|
|
*
|
|
|
|
|
* OR, define the relation in the model definition:
|
|
|
|
|
*
|
|
|
|
|
* - Definition of Customer model:
|
|
|
|
|
* ```json
|
|
|
|
|
* {
|
|
|
|
|
"name": "Customer",
|
|
|
|
|
"base": "PersistedModel",
|
|
|
|
|
"idInjection": true,
|
|
|
|
|
"properties": {
|
|
|
|
|
"name": {
|
|
|
|
|
"type": "string"
|
|
|
|
|
},
|
|
|
|
|
"age": {
|
|
|
|
|
"type": "number"
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
"validations": [],
|
|
|
|
|
"relations": {
|
|
|
|
|
"emails": {
|
|
|
|
|
"type": "embedsMany",
|
|
|
|
|
"model": "EmailAddress",
|
|
|
|
|
"property": "emailList",
|
|
|
|
|
"options": {
|
|
|
|
|
"validate": true,
|
|
|
|
|
"forceId": false
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
"acls": [],
|
|
|
|
|
"methods": {}
|
|
|
|
|
}
|
|
|
|
|
* ```
|
|
|
|
|
*
|
|
|
|
|
* - Definition of EmailAddress model:
|
|
|
|
|
* ```json
|
|
|
|
|
* {
|
|
|
|
|
"name": "EmailAddress",
|
|
|
|
|
"base": "Model",
|
|
|
|
|
"idInjection": true,
|
|
|
|
|
"properties": {
|
|
|
|
|
"label": {
|
|
|
|
|
"type": "string"
|
|
|
|
|
},
|
|
|
|
|
"address": {
|
|
|
|
|
"type": "string"
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
"validations": [],
|
|
|
|
|
"relations": {},
|
|
|
|
|
"acls": [],
|
|
|
|
|
"methods": {}
|
|
|
|
|
}
|
|
|
|
|
* ```
|
|
|
|
|
*
|
|
|
|
|
* Sample embedded model data:
|
|
|
|
|
* ```javascript
|
|
|
|
|
* {
|
|
|
|
|
id: 1,
|
|
|
|
|
name: 'John Smith',
|
|
|
|
|
emails: [{
|
|
|
|
|
label: 'work',
|
|
|
|
|
address: 'john@xyz.com'
|
|
|
|
|
}, {
|
|
|
|
|
label: 'home',
|
|
|
|
|
address: 'john@gmail.com'
|
|
|
|
|
}]
|
|
|
|
|
}
|
|
|
|
|
* ```
|
|
|
|
|
*
|
|
|
|
|
* Supported helper methods:
|
|
|
|
|
* - customer.emails()
|
|
|
|
|
* - customer.emails.create()
|
|
|
|
|
* - customer.emails.build()
|
|
|
|
|
* - customer.emails.findById()
|
|
|
|
|
* - customer.emails.destroyById()
|
|
|
|
|
* - customer.emails.updateById()
|
|
|
|
|
* - customer.emails.exists()
|
|
|
|
|
* - customer.emails.add()
|
|
|
|
|
* - customer.emails.remove()
|
|
|
|
|
* - customer.emails.at()
|
|
|
|
|
* - customer.emails.value()
|
|
|
|
|
*
|
|
|
|
|
* @param {Object|String} modelTo Model object (or String name of model) to which you are creating the relationship.
|
|
|
|
|
* @options {Object} params Configuration parameters; see below.
|
|
|
|
|
* @property {String} as Name of the property in the referring model that corresponds to the foreign key field in the related model.
|
|
|
|
|
* @property {String} property Name of the property for the embedded item.
|
|
|
|
|
* @property {Any} default The default value.
|
|
|
|
|
* @property {Object} options Options to specify for the relationship.
|
|
|
|
|
* @property {Boolean} options.forceId Force generation of id for embedded items. Default is false.
|
|
|
|
|
* @property {Boolean} options.validate Denote if the embedded items should be validated. Default is true.
|
|
|
|
|
* @property {Boolean} options.persistent Denote if the embedded items should be persisted. Default is false.
|
|
|
|
|
* @property {String} polymorphic Define a polymorphic relation name.
|
|
|
|
|
* @property {Object|Function} scope Explicitly define additional scopes.
|
|
|
|
|
* @property {Object} properties Properties inherited from the parent object.
|
|
|
|
|
* @property {Function} methods Scoped methods for the given relation.
|
|
|
|
|
*/
|
2014-08-19 20:10:35 +00:00
|
|
|
|
RelationMixin.embedsMany = function embedsMany(modelTo, params) {
|
2014-08-13 09:28:23 +00:00
|
|
|
|
return RelationDefinition.embedsMany(this, modelTo, params);
|
2014-07-27 14:30:45 +00:00
|
|
|
|
};
|