forked from briankircho/mongoose-schema-extend
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
80 lines (69 loc) · 2.36 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
var mongoose = require('mongoose'),
owl = require('owl-deepcopy');
var Schema = mongoose.Schema,
Model = mongoose.Model;
/**
* Add a new function to the schema prototype to create a new schema by extending an existing one
*/
Schema.prototype.extend = function(obj, options) {
// Deep clone the existing schema so we can add without changing it
var newSchema = owl.deepCopy(this);
// Fix for callQueue arguments, todo: fix clone implementation
newSchema.callQueue.forEach(function(k) {
var args = [];
for(var i in k[1]) {
args.push(k[1][i]);
}
k[1] = args;
});
// Override the existing options with any newly supplied ones
for(var k in options) {
newSchema.options[k] = options[k];
}
// This adds all the new schema fields
newSchema.add(obj);
var key = newSchema.options.discriminatorKey;
if(key) {
// If a discriminatorField is in the schema options, add a new field to store model names
var discriminatorField = {};
discriminatorField[key] = { type : String };
newSchema.add(discriminatorField);
// When new documents are saved, include the model name in the discriminatorField
// if it is not set already.
newSchema.pre('save', function(next) {
if(this[key] === null || this[key] === undefined) {
this[key] = this.constructor.modelName;
}
next();
});
}
return newSchema;
};
/**
* Wrap the model init to set the prototype based on the discriminator field
*/
var oldInit = Model.prototype.init;
Model.prototype.init = function(doc, query, fn) {
var key = this.schema.options['discriminatorKey'];
if(key) {
// If the discriminatorField contains a model name, we set the documents prototype to that model
var type = doc[key];
if(type) {
// this will throw exception if the model isn't registered
var model = this.db.model(type);
var newFn = function() {
// this is pretty ugly, but we need to run the code below before the callback
process.nextTick(function() {
fn.apply(this, arguments);
});
}
var modelInstance = new model();
this.schema = model.schema;
var obj = oldInit.call(this, doc, query, newFn);
obj.__proto__ = model.prototype;
return obj;
}
}
// If theres no discriminatorKey we can just call the original method
return oldInit.apply(this, arguments);
}