Skip to content

Commit

Permalink
Models now have their own custom model.Instance classes
Browse files Browse the repository at this point in the history
These classes inherit from Instance and provide virtuals and methods
via their prototype, allowing for considerably more lightweight instances
creation and (hopefully) functional intellisense for virtuals and methods.
  • Loading branch information
notheotherben committed Jan 10, 2014
1 parent 861ecb2 commit ce0c435
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 42 deletions.
80 changes: 46 additions & 34 deletions lib/Instance.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@ function Instance(model, doc, isNew) {
/// </signature>

"use strict";

if(!(this instanceof Instance)) return new Instance(model, doc, isNew);

if(!isNew) model.fromSource(doc);

Expand All @@ -37,38 +35,6 @@ function Instance(model, doc, isNew) {

this.__extendSchema();

for (var methodName in model.options.methods) {
(function (methodName) {
Object.defineProperty(this, methodName, {
value: (function () {
return model.options.methods[methodName].apply(this, arguments);
}).bind(this)
});
}).bind(this)(methodName);
}

for (var propertyName in model.options.virtuals) {
(function (propertyName) {
if(typeof model.options.virtuals[propertyName] == 'function')
Object.defineProperty(this, propertyName, {
get: (function () {
return model.options.virtuals[propertyName].call(this);
}).bind(this),
enumerable: true
});
else
Object.defineProperty(this, propertyName, {
get: (function () {
return model.options.virtuals[propertyName].get.call(this);
}).bind(this),
set: (function(value) {
return model.options.virtuals[propertyName].set.call(this, value);
}).bind(this),
enumerable: true
});
}).bind(this)(propertyName);
}

for(var i = 0; i < model.database.plugins.length; i++)
if(model.database.plugins[i].newInstance)
model.database.plugins[i].newInstance.call(this, model, doc, isNew);
Expand Down Expand Up @@ -228,6 +194,52 @@ Instance.prototype.__extendSchema = function() {
}
};

Instance.forModel = function(model) {
/// <summary>Creates an instance wrapper for the specified model</summary>
/// <param name="model" type="Model">The model which the instance wraps</param>
/// <return type="Function"/>

function ModelInstance(doc, isNew) {
/// <signature>
/// <summary>Creates a new model instance for the specified document</summary>
/// <param name="doc" type="Object">The document which the instance should wrap</param>
/// </signature>
/// <signature>
/// <summary>Creates a new model instance for the specified document</summary>
/// <param name="doc" type="Object">The document which the instance should wrap</param>
/// <param name="isNew" type="Boolean">Whether or not the document was sourced from the database</param>
/// </signature>

Instance.call(this, model, doc, isNew);
}

var proto = {};

_.each(model.options.virtuals, function(property, name) {
if('function' == typeof property)
Object.defineProperty(proto, name, {
get: property,
enumerable: true
});
else
Object.defineProperty(proto, name, {
get: property.get,
set: property.set,
enumerable: true
});
});

proto.__proto__ = Instance.prototype;

_.each(model.options.methods, function(method, name) {
proto[name] = method;
});

ModelInstance.prototype = proto;

return ModelInstance;
};

var diffPatch = Instance.diff = function (oldDoc, newDoc, path) {
/// <signature>
/// <summary>Creates a differential update query for use by MongoDB</summary>
Expand Down
7 changes: 6 additions & 1 deletion lib/Model.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@ function Model(database, collection, schema, options) {
enumerable: false
});

Object.defineProperty(this, 'Instance', {
value: Instance.forModel(this),
enumerable: false
});


var extraValidators = [];
for(var i = 0; i < database.plugins.length; i++) {
Expand Down Expand Up @@ -158,7 +163,7 @@ Model.prototype.wrap = function (document, isNew) {
/// <returns type="Instance"/>
/// </signature>

return new Instance(this, document, isNew);
return new this.Instance(document, isNew);
};

Model.prototype.onRetrieved = function(results, callback, wrapper) {
Expand Down
14 changes: 7 additions & 7 deletions test/instance.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ describe('orm', function () {
preprocessors: []
})

var i = new Instance(model, {
var i = new model.Instance({
id: 'custom_id',
name: 'name'
});
Expand All @@ -63,7 +63,7 @@ describe('orm', function () {
]
});

var i = new Instance(model, {
var i = new model.Instance({
_id: 'custom_id',
uglyName: 'value'
});
Expand All @@ -78,7 +78,7 @@ describe('orm', function () {
}
});

var i = new Instance(model, {
var i = new model.Instance({
_id: 'custom_id'
});

Expand All @@ -96,7 +96,7 @@ describe('orm', function () {
}
});

var i = new Instance(model, {
var i = new model.Instance({
_id: 'custom_id'
});

Expand All @@ -110,7 +110,7 @@ describe('orm', function () {
}
});

var i = new Instance(model, {
var i = new model.Instance({
_id: 'custom_id',
firstname: 'Billy',
lastname: 'Bob'
Expand All @@ -132,7 +132,7 @@ describe('orm', function () {
}
});

var i = new Instance(model, {
var i = new model.Instance({
_id: 'custom_id',
firstname: 'Billy',
lastname: 'Bob'
Expand All @@ -153,7 +153,7 @@ describe('orm', function () {
preprocessors: []
});

var i = new Instance(model, {
var i = new model.Instance({
id: 'custom_id',
name: 'name'
});
Expand Down

0 comments on commit ce0c435

Please sign in to comment.