UNPKG

5.47 kBJavaScriptView Raw
1'use strict';
2function Relationship(config) {
3 this.ORM = config.ORM;
4 this.type = config.type;
5 this.modelFactoryName = config.modelFactoryName;
6 // TEMP
7 if(!config.throughTableName) {
8 this.identifer = {
9 parent: config.parentIdentifer,
10 child: config.childIdentifer,
11 };
12 } else {
13 this.identifer = {
14 parent_0: config.parentIdentifer_0,
15 child_0: config.childIdentifer_0,
16 parent_1: config.parentIdentifer_1,
17 child_1: config.childIdentifer_1
18 };
19 this.throughTableName = config.throughTableName;
20 Relationship.createThroughModelFactory(this.ORM, this.modelFactoryName, this.throughTableName, this.identifer);
21 }
22}
23
24Relationship.Types = {
25 belongsToOne: 'BELONGS_TO_ONE',
26 belongsToMany: 'BELONGS_TO_MANY',
27 hasOne: 'HAS_ONE',
28 hasMany: 'HAS_MANY'
29};
30
31//
32// Private
33//
34Relationship.createThroughModelFactory = function(ORM, modelFactoryName, tableName, identifer) {
35 // Base model
36 var model = {
37 attributes: {}
38 };
39 // Create table attribute
40 model.attributes[identifer.parent_0] = {};
41 model.attributes[identifer.parent_1] = {};
42
43 // Create relation
44 model.attributes[modelFactoryName] = function(context) {
45 return context.belongsToOne(modelFactoryName, identifer.child_1, identifer.parent_1);
46 };
47
48 // Create new factory if it doesn't exist
49 // If it does, update the factory's attributes to include identifer
50 if(!ORM.models.hasOwnProperty(tableName)) {
51 ORM.Model.extend(tableName, model);
52 } else {
53 ORM.models[tableName].addTableAttributes(model.attributes);
54 }
55};
56
57//
58// Create
59//
60
61Relationship.prototype.createBelongsToOne = function(attributes, options) {
62 return ORM.models[this.modelFactoryName].create(attributes, options);
63};
64
65Relationship.prototype.createBelongsToMany = function(attributesMany, options) {
66 var promises = [];
67 attributesMany.map((attributes) => {
68 var promise = this.createBelongsToOne(attributes, options);
69 promises.push(promise);
70 });
71 return Promise.all(promises);
72};
73
74Relationship.prototype.createHasOne = function(attributes, parentModel, options) {
75 var newAttributes = Object.assign({}, attributes, {
76 [this.identifer.child]: parentModel[this.identifer.parent]
77 });
78 return ORM.models[this.modelFactoryName].create(newAttributes, options);
79};
80
81Relationship.prototype.createHasMany = function(attributesMany, parentModel, options) {
82 var promises = [];
83 attributesMany.map((attributes) => {
84 var promise = this.createHasOne(attributes, parentModel, options);
85 promises.push(promise);
86 });
87 return Promise.all(promises);
88};
89
90//
91// Attach
92//
93
94Relationship.prototype.attachAsAttribute = function(attributes, parentModel) {
95 var newAttributes = {};
96 newAttributes[this.identifer.child] = parentModel[this.identifer.parent];
97 return Object.assign(attributes, newAttributes);
98};
99
100// Note: parameter parentModel needs to be renamed,
101// in many-to-many the related models are siblings.
102// Parent should be refering to the Through table only.
103Relationship.prototype.attach = function(childModel, parentModels, options) {
104 var promises = [];
105 parentModels.forEach(function(parentModel) {
106 var attributes = {
107 [this.identifer.parent_0]: childModel[this.identifer.child_0],
108 [this.identifer.parent_1]: parentModel[this.identifer.child_1]
109 };
110 var promise = this.ORM.models[this.throughTableName].create(attributes, options);
111 promises.push(promise);
112 }, this);
113 return Promise.all(promises);
114};
115
116//
117// Include
118//
119
120Relationship.prototype.include = function(table, childModel) {
121 var self = this;
122 var promises = [];
123 var query = {};
124 var promise;
125 switch(self.type) {
126 case Relationship.Types.hasOne:
127 case Relationship.Types.belongsToOne: {
128 query[self.identifer.parent] = childModel[self.identifer.child];
129 promise = self.ORM.models[self.modelFactoryName].findOne(query);
130 break;
131 }
132 case Relationship.Types.belongsToMany : {
133 query = {};
134 var include = [self.modelFactoryName];
135 // selfThroughIdentifer, selfIdentifer
136 promise = new Promise(function(resolve, reject) {
137 var models = [];
138 query[self.identifer.parent_0] = childModel[self.identifer.child_0];
139 // Get all through models
140 self.ORM.models[self.throughTableName].find(query, {
141 include: include
142 })
143 // Extract desired model in through model
144 .then(function(throughModels) {
145 throughModels.forEach(function(throughModel) {
146 models.push(throughModel[self.modelFactoryName]);
147 });
148 resolve(models);
149 })
150 .catch(function(error) {
151 reject(error);
152 });
153 });
154 promises.push(promise);
155 break;
156 }
157 case Relationship.Types.hasMany: {
158 query = {};
159 query[self.identifer.child] = childModel[self.identifer.parent];
160 promise = self.ORM.models[self.modelFactoryName].find(query);
161 promises.push(promise);
162 break;
163 }
164 }
165 return promise.then((model) => {
166 childModel[table] = model;
167 return childModel;
168 });
169};
170
171//
172// Helper
173//
174Relationship.prototype.getThroughTable = function() {
175 return (this.type === Relationship.Types.belongsToMany)
176 ? this.throughTableName
177 : this.modelFactoryName;
178};
179
180
181
182module.exports = Relationship;
\No newline at end of file