skul
Version:
SKuL - SQL query manager
340 lines (267 loc) • 8.65 kB
JavaScript
/*
* lib/skul/relationship.js
*
* SKuL relationship methods
*
* Author: Paul Duthoit
* Copyright(c) 2016 Paul Duthoit
*/
// Dependencies
var _ = require('underscore');
/*
* Add a relationship
*
* @params {String} type
* @params {String} key
* @params {Object} relationship
*
* @api public
*/
module.exports.addRelationship = function(type, key, relationship) {
// Check arguments
if(!(typeof type === "string" && _.contains([ 'belongsTo', 'hasMany', 'hasOne', 'hasManyCustom', 'hasOneCustom', 'hasManyThrough', 'hasOneThrough' ], type)))
throw new Error("type have to be a string defined as belongsTo, hasMany, hasOne, hasManyCustom, hasOneCustom, hasManyThrough or hasOneThrough");
if(typeof key !== "string")
throw new Error("key have to be a string");
if(typeof relationship !== "object")
throw new Error("relationship have to be an object");
// If type is basic
if(type === 'belongsTo' || type === 'hasMany' || type === 'hasOne') {
// Check relationship argument
if(!(relationship.model instanceof this._self))
throw new Error("relationship.model have to be a Skul.Model object");
if(typeof relationship.foreignKey !== "string")
throw new Error("relationship.foreignKey have to be a string");
// Set relationship
this.relationships[key] = relationship;
this.relationships[key].type = type;
}
// If type is hasOneCustom
else if(type === 'hasOneCustom') {
// Check relationship argument
if(!(typeof relationship.model === "object" && relationship.model !== null))
throw new Error("relationship.model have to be an object");
if(!(relationship.model['$model'] instanceof this._self))
throw new Error("relationship.model.$model have to be a Skul.Model object");
if(!(typeof relationship.model['$alias'] === "string"))
throw new Error("relationship.model.$alias have to be a string");
if(!(relationship.joinRaw instanceof Array))
throw new Error("relationship.joinRaw have to be an array");
// Set relationship
this.relationships[key] = relationship;
this.relationships[key].type = type;
}
// If type is hasManyCustom
else if(type === 'hasManyCustom') {
// Check relationship argument
if(!(typeof relationship.model === "object" && relationship.model !== null))
throw new Error("relationship.model have to be an object");
if(!(relationship.model['$model'] instanceof this._self))
throw new Error("relationship.model.$model have to be a Skul.Model object");
if(!(typeof relationship.model['$alias'] === "string"))
throw new Error("relationship.model.$alias have to be a string");
if(!(!relationship.joinRaw || relationship.joinRaw instanceof Array))
throw new Error("relationship.joinRaw have to be an array");
if(!(typeof relationship.foreignKey === "object" && relationship.foreignKey !== null))
throw new Error("relationship.foreignKey have to be an object");
if(!(typeof relationship.foreignKey['$alias'] === "string"))
throw new Error("relationship.foreignKey.$alias have to be a string");
if(!(typeof relationship.foreignKey['$key'] === "string"))
throw new Error("relationship.foreignKey.$key have to be a string");
// Set relationship
this.relationships[key] = relationship;
this.relationships[key].type = type;
}
// If type is through
else if(type === 'hasManyThrough' || type === 'hasOneThrough') {
// Check relationship argument
if(!(relationship instanceof Array))
throw new Error("relationship have to be an array");
// Loop over relationships
_.each(relationship, function(relItem) {
// Check relItem argument
if(!(typeof relItem.type === "string" && _.contains([ 'belongsTo', 'hasMany', 'hasOne' ], relItem.type)))
throw new Error("relationship.$.type have to be a string defined as belongsTo, hasMany or hasOne");
if(!(relItem.model instanceof this._self))
throw new Error("relationship.$.model have to be a Skul.Model object");
if(typeof relItem.foreignKey !== "string")
throw new Error("relationship.$.foreignKey have to be a string");
}.bind(this));
// Set relationship
this.relationships[key] = { joins: relationship, type: type };
}
};
/**
* Remove a relationship
*
* @params {String} key
*
* @api public
*/
module.exports.removeRelationship = function(key) {
// Check arguments
if(typeof key !== "string")
throw new Error("key have to be a string");
// Delete relationship if exists
if(typeof this.relationships[key] !== "undefined") {
delete this.relationships[key];
}
};
/**
* Get all relationships
*
* @params {string} [type]
*
* @return {Object}
* @api public
*/
module.exports.getRelationships = function(type) {
// Check arguments
if(!(typeof type === "string" && _.contains([ 'belongsTo', 'hasMany', 'hasOne', 'hasManyCustom', 'hasOneCustom', 'hasManyThrough', 'hasOneThrough' ], type)) && typeof type !== "undefined")
throw new Error("type have to be a string defined as belongsTo, hasMany, hasOne, hasManyCustom, hasOneCustom, hasManyThrough or hasOneThrough");
// If type is defined
if(type) {
// Data
var requestedRelationships = {};
// Loop over relationships
_.each(this.relationships, function(obj, key) {
if(obj.type === type) {
requestedRelationships[key] = obj;
}
});
// Return relationships
return requestedRelationships;
}
// If type is not defined
else {
// Return relationships
return this.relationships;
}
};
/**
* Get a relationship
*
* @params {String} key
*
* @return {Object}
* @api public
*/
module.exports.getRelationship = function(key) {
// Check arguments
if(typeof key !== "string")
throw new Error("key have to be a string");
// Return relationship
return this.relationships[key];
};
/*
* Get relationship keys
*
* @return {Array}
* @api public
*/
module.exports.getRelationshipKeys = function(type) {
// Check arguments
if (!(
typeof type === "undefined"
|| (typeof type === "string" && _.contains([ 'belongsTo', 'hasMany', 'hasOne', 'hasManyCustom', 'hasOneCustom', 'hasManyThrough', 'hasOneThrough' ], type))
|| (type instanceof Array && _.intersection([ 'belongsTo', 'hasMany', 'hasOne', 'hasManyCustom', 'hasOneCustom', 'hasManyThrough', 'hasOneThrough' ], type).length == type.length)
)) {
throw new Error("type have to be a string or an array defined as / including belongsTo, hasMany, hasOne, hasManyCustom, hasOneCustom, hasManyThrough or hasOneThrough");
}
// Return typped relationship keys
if (type) {
return _.compact(_.map(this.relationships, function(obj, key) {
if (typeof type == 'string') return obj.type === type && key;
else if (type instanceof Array) return _.contains(type, obj.type) && key;
else return null;
}));
}
// Return all relationship keys
else {
return _.map(this.relationships, function(obj, key) { return key; });
}
};
/*
* Add belongsTo relationship
*
* @params {String} key
* @params {Object} relationship
*
* @api public
*/
module.exports.belongsTo = function(key, relationship) {
// Add relationship
this.addRelationship('belongsTo', key, relationship);
};
/*
* Add hasMany relationship
*
* @params {String} key
* @params {Object} relationship
*
* @api public
*/
module.exports.hasMany = function(key, relationship) {
// Add relationship
this.addRelationship('hasMany', key, relationship);
};
/*
* Add hasOne relationship
*
* @params {String} key
* @params {Object} relationship
*
* @api public
*/
module.exports.hasOne = function(key, relationship) {
// Add relationship
this.addRelationship('hasOne', key, relationship);
};
/*
* Add hasManyCustom relationship
*
* @params {String} key
* @params {Object} relationship
*
* @api public
*/
module.exports.hasManyCustom = function(key, relationship) {
// Add relationship
this.addRelationship('hasManyCustom', key, relationship);
};
/*
* Add hasOneCustom relationship
*
* @params {String} key
* @params {Object} relationship
*
* @api public
*/
module.exports.hasOneCustom = function(key, relationship) {
// Add relationship
this.addRelationship('hasOneCustom', key, relationship);
};
/*
* Add hasManyThrough relationship
*
* @params {String} key
* @params {Object} relationship
*
* @api public
*/
module.exports.hasManyThrough = function(key, relationship) {
// Add relationship
this.addRelationship('hasManyThrough', key, relationship);
};
/*
* Add hasOneThrough relationship
*
* @params {String} key
* @params {Object} relationship
*
* @api public
*/
module.exports.hasOneThrough = function(key, relationship) {
// Add relationship
this.addRelationship('hasOneThrough', key, relationship);
};