waterline
Version:
An ORM for Node.js and the Sails framework
93 lines (72 loc) • 4.63 kB
JavaScript
/**
* Module dependencies
*/
var util = require('util');
var assert = require('assert');
var _ = require('@sailshq/lodash');
var getAttribute = require('./get-attribute');
/**
* isExclusive()
*
* Determine whether this association is "exclusive" -- meaning that it is
* a two-way, plural ("collection") association, whose `via` points at a
* singular ("model") on the other side.
*
* > Note that "through" associations do not count. Although the "via" does
* > refer to a singular ("model") association in the intermediate junction
* > model, the underlying logical association is still non-exclusive.
* > i.e. the same child record can be added to the "through" association
* > of multiple different parent records.
*
* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
* @param {String} attrName [the name of the association in question]
* @param {String} modelIdentity [the identity of the model this association belongs to]
* @param {Ref} orm [the Waterline ORM instance]
* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
* @returns {Boolean}
*/
module.exports = function isExclusive(attrName, modelIdentity, orm) {
if (!_.isString(attrName)) {
throw new Error('Consistency violation: Must specify `attrName` as a string. But instead, got: '+util.inspect(attrName, {depth:5})+'');
}
if (!_.isString(modelIdentity)) {
throw new Error('Consistency violation: Must specify `modelIdentity` as a string. But instead, got: '+util.inspect(modelIdentity, {depth:5})+'');
}
if (_.isUndefined(orm)) {
throw new Error('Consistency violation: Must pass in `orm` (a reference to the Waterline ORM instance). But instead, got: '+util.inspect(orm, {depth:5})+'');
}
// ╦ ╔═╗╔═╗╦╔═ ╦ ╦╔═╗ ┌─┐┌─┐┌─┐┌─┐┌─┐┬┌─┐┌┬┐┬┌─┐┌┐┌ ┬ ┌┬┐┌─┐┌┬┐┌─┐┬ ┌─┐
// ║ ║ ║║ ║╠╩╗ ║ ║╠═╝ ├─┤└─┐└─┐│ ││ │├─┤ │ ││ ││││ ┌┼─ ││││ │ ││├┤ │ └─┐
// ╩═╝╚═╝╚═╝╩ ╩ ╚═╝╩ ┴ ┴└─┘└─┘└─┘└─┘┴┴ ┴ ┴ ┴└─┘┘└┘ └┘ ┴ ┴└─┘─┴┘└─┘┴─┘└─┘
// Look up the containing model for this association, and the attribute definition itself.
var attrDef = getAttribute(attrName, modelIdentity, orm);
assert(attrDef.model || attrDef.collection, 'Attempting to check whether attribute `'+attrName+'` of model `'+modelIdentity+'` is an "exclusive" association, but it\'s not even an association in the first place!');
// ┌┐┌┌─┐┬ ┬ ╔═╗╦ ╦╔═╗╔═╗╦╔═ ╦╔╦╗ ╔═╗╦ ╦╔╦╗
// ││││ ││││ ║ ╠═╣║╣ ║ ╠╩╗ ║ ║ ║ ║║ ║ ║
// ┘└┘└─┘└┴┘┘ ╚═╝╩ ╩╚═╝╚═╝╩ ╩ ╩ ╩ ╚═╝╚═╝ ╩
// If this association is singular, then it is not exclusive.
if (!attrDef.collection) {
return false;
}//-•
// If it has no `via`, then it is not two-way, and also not exclusive.
if (!attrDef.via) {
return false;
}//-•
// If it has a "through" junction model defined, then it is not exclusive.
if (attrDef.through) {
return false;
}//-•
// If its `via` points at a plural association, then it is not exclusive.
// > Note that, to do this, we look up the attribute on the OTHER model
// > that is pointed at by THIS association's `via`.
var viaAttrDef = getAttribute(attrDef.via, attrDef.collection, orm);
if (viaAttrDef.collection) {
return false;
}//-•
// Otherwise, its `via` must be pointing at a singular association, so it's exclusive!
return true;
};
// Quick test:
/*```
require('./lib/waterline/utils/ontology/is-exclusive')('pets', 'user', { collections: { user: { attributes: { id: { type: 'string', required: true, unique: true }, age: { type: 'number', required: false }, foo: { type: 'string', required: true }, pets: { collection: 'pet', via: 'owner' } }, primaryKey: 'id', hasSchema: true}, pet: { attributes: { id: { type:'number', required: true, unique: true }, owner: { model: 'user' } }, primaryKey: 'id', hasSchema: true } } });
```*/