Skip to content

Commit e1e7f3e

Browse files
committed
Merge pull request #2480 from alabid/gh-2167
gh-2167 give discriminators access to their own instance or class methods
2 parents 6412dd6 + 0bcd28d commit e1e7f3e

File tree

2 files changed

+85
-7
lines changed

2 files changed

+85
-7
lines changed

lib/model.js

+54-7
Original file line numberDiff line numberDiff line change
@@ -710,6 +710,10 @@ Model.discriminator = function discriminator (name, schema) {
710710
this.discriminators[name] = this.db.model(name, schema, this.collection.name);
711711
this.discriminators[name].prototype.__proto__ = this.prototype;
712712

713+
// apply methods and statics
714+
applyMethods(this.discriminators[name], schema);
715+
applyStatics(this.discriminators[name], schema);
716+
713717
return this.discriminators[name];
714718
};
715719

@@ -2545,13 +2549,9 @@ Model.compile = function compile (name, schema, collectionName, connection, base
25452549
, collectionOptions
25462550
);
25472551

2548-
// apply methods
2549-
for (var i in schema.methods)
2550-
model.prototype[i] = schema.methods[i];
2551-
2552-
// apply statics
2553-
for (var i in schema.statics)
2554-
model[i] = schema.statics[i];
2552+
// apply methods and statics
2553+
applyMethods(model, schema);
2554+
applyStatics(model, schema);
25552555

25562556
model.schema = model.prototype.schema;
25572557
model.options = model.prototype.options;
@@ -2560,6 +2560,53 @@ Model.compile = function compile (name, schema, collectionName, connection, base
25602560
return model;
25612561
};
25622562

2563+
/*!
2564+
* Register methods for this model
2565+
*
2566+
* @param {Model} model
2567+
* @param {Schema} schema
2568+
*/
2569+
var applyMethods = function(model, schema) {
2570+
for (var i in schema.methods) {
2571+
if (typeof schema.methods[i] === 'function') {
2572+
model.prototype[i] = schema.methods[i];
2573+
} else {
2574+
(function(_i) {
2575+
Object.defineProperty(model.prototype, _i, {
2576+
get: function() {
2577+
var h = {};
2578+
for (var k in schema.methods[_i]) {
2579+
h[k] = schema.methods[_i][k].bind(this);
2580+
}
2581+
return h;
2582+
}
2583+
});
2584+
})(i);
2585+
}
2586+
}
2587+
2588+
for (var i in schema.methods)
2589+
model.prototype[i] = schema.methods[i];
2590+
};
2591+
2592+
/*!
2593+
* Register statics for this model
2594+
* @param {Model} model
2595+
* @param {Schema} schema
2596+
*/
2597+
var applyStatics = function(model, schema) {
2598+
for (var i in schema.statics) {
2599+
// use defineProperty so that static props can't be overwritten
2600+
Object.defineProperty(model, i, {
2601+
value: schema.statics[i],
2602+
writable: false
2603+
});
2604+
}
2605+
2606+
for (var i in schema.statics)
2607+
model[i] = schema.statics[i];
2608+
};
2609+
25632610
/*!
25642611
* Subclass this model with `conn`, `schema`, and `collection` settings.
25652612
*

test/model.discriminator.test.js

+31
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ var start = require('./common')
66
, mongoose = start.mongoose
77
, Schema = mongoose.Schema
88
, assert = require('assert')
9+
, util = require('util')
910
, clone = require('../lib/utils').clone
1011
, random = require('../lib/utils').random;
1112

@@ -83,6 +84,36 @@ describe('model', function() {
8384
done();
8485
});
8586

87+
it('can define static and instance methods', function(done) {
88+
function BossBaseSchema() {
89+
Schema.apply(this, arguments);
90+
91+
this.add({
92+
name: String,
93+
createdAt: Date
94+
});
95+
}
96+
util.inherits(BossBaseSchema, Schema);
97+
98+
var PersonSchema = new BossBaseSchema();
99+
var BossSchema = new BossBaseSchema({ department: String });
100+
BossSchema.methods.myName = function(){
101+
return this.name;
102+
};
103+
BossSchema.statics.currentPresident = function(){
104+
return 'obama';
105+
};
106+
var Person = db.model('Person', PersonSchema);
107+
var Boss = Person.discriminator('Boss', BossSchema);
108+
109+
var boss = new Boss({name:'Bernenke'});
110+
assert.equal(boss.myName(), 'Bernenke');
111+
assert.equal(boss.notInstanceMethod, undefined);
112+
assert.equal(Boss.currentPresident(), 'obama');
113+
assert.equal(Boss.notStaticMethod, undefined);
114+
done();
115+
});
116+
86117
it('sets schema root discriminator mapping', function(done) {
87118
assert.deepEqual(PersonSchema.discriminatorMapping, { key: '__t', value: null, isRoot: true });
88119
done();

0 commit comments

Comments
 (0)