From b1457f28b9ec982aa397edcb20ab1935105ca912 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Fri, 27 Jun 2014 08:56:44 -0700 Subject: [PATCH] fixed bug with extend added Graviton.isModel fixed race conditions in tests --- graviton.js | 2 + lib/model.js | 16 +++++- lib/relations.js | 8 +-- test/graviton-test.js | 115 +++++++++++++++++++++++++++++++----------- 4 files changed, 105 insertions(+), 36 deletions(-) diff --git a/graviton.js b/graviton.js index 3b9c1e0..a4c2135 100644 --- a/graviton.js +++ b/graviton.js @@ -50,6 +50,8 @@ Graviton.setProperty = function(obj, key, val) { } }; +Graviton.isModel = isModel; + // use this to declare new models // options contain the relations etc. Graviton.define = function(collectionName, options) { diff --git a/lib/model.js b/lib/model.js index 0e9debb..ef20b79 100644 --- a/lib/model.js +++ b/lib/model.js @@ -36,13 +36,19 @@ Model = function(collectionName, obj, options) { _.extend(this, options.properties); }; +isModel = function(obj) { + return (obj instanceof Graviton.Model || Graviton.Model.prototype.isPrototypeOf(obj)); +}; + + // for creating a custom class to user for model transforms Model.extend = function(proto) { var self = this; var Model = function(collectionName, obj, options) { self.call(this, collectionName, obj, options); }; - Model.prototype = _.extend({}, this.prototype, proto); + Model.prototype = Object.create(this.prototype); + _.extend(Model.prototype, proto); Model.extend = this.extend; return Model; }; @@ -92,13 +98,19 @@ Model.prototype.savedState = function() { return this._savedState; }; +Model.prototype.update = function(modifier, options, callback) { + var args = _.toArray(arguments); + args.unshift({_id: this._id}); + return this._collection.update.apply(this, args); +}; + // insert or update // TODO: track the attributes that have changed and only update those Model.prototype.save = function() { if (!this.persist()) { var diff = Graviton.mongoDiff(this.savedState(), this.attributes); if (!_.isEmpty(diff.operators)) { - this._collection.update(this._id, diff.operators); + this.update(diff.operators); this.syncSavedState(); return {updated: true, warnings: diff.warnings}; } diff --git a/lib/relations.js b/lib/relations.js index 199d24f..0fe9d06 100644 --- a/lib/relations.js +++ b/lib/relations.js @@ -10,7 +10,7 @@ Relation = function(model, config) { Relation.prototype.constructor = Relation; Relation.prototype.build = function(obj) { - if (obj instanceof Graviton.Model) return obj; + if (isModel(obj)) return obj; if (_.isObject(obj)) return this._collection.build(obj); }; // inserts model if it doesn't have an id - typically called by add @@ -148,7 +148,7 @@ HasMany.prototype.add = function(model) { model = this.build(model); model.set(this._foreignKey, this._model._id); - Relation.prototype.persist.call(this, model); + model.persist(); var set = {$set: {}}; set['$set'][this._foreignKey] = this._model._id; @@ -164,10 +164,10 @@ hasOne = function(model, config) { var rel = new Relation(model, config); return function(model) { if (model) { - model = Relation.prototype.build.call(rel, model); + model = rel.build(model); if (model.get(rel._foreignKey) !== rel._model._id) { model.set(rel._foreignKey, rel._model._id); - } + } model.save(); return model; } else { diff --git a/test/graviton-test.js b/test/graviton-test.js index 76be68f..31e3b29 100644 --- a/test/graviton-test.js +++ b/test/graviton-test.js @@ -1,8 +1,12 @@ + +var _klasses = []; + var init = function(klass) { - allowAll(klass); if (Meteor.isServer) { - klass.remove({}); + allowAll(klass); } + _klasses.push(klass); + }; var allowAll = function(klass) { @@ -19,7 +23,7 @@ var allowAll = function(klass) { }); }; -Car = Graviton.Car = Graviton.define("cars", { +Car = Graviton.define("cars", { initialize: function() { this.set('price', this.get('price') - 2); }, @@ -97,43 +101,50 @@ Window = Graviton.define("windows", { persist: false }); +////////////// setup +var doc, c, w; +var setup = function() { + if (Meteor.isServer) { + _.each(_klasses, function(klass) { + klass.remove({}); + }); + } + -var doc = {color: 'red', speed: 'fast', price: 100, engine: {type: 'combustion', cylinders: 8}}; -doc._id = Car.insert(doc); - -var c = Car.findOne(doc._id); -if (Meteor.isClient) window.c = c; - -c.manufacturer({name: "Audi", location: "Germany"}); - -c.wheels.add({}); -c.wheels.add([{}, {tread: 'worn'}, {}]); - -var w = Wheel.build({}); -w.save(); - -w.set("isFlat", true); -w.save(); + doc = {color: 'red', speed: 'fast', price: 100, engine: {type: 'combustion', cylinders: 8}}; + doc._id = Car.insert(doc); -c.drivers.add({name: "Mario"}); -c.drivers.add({name: "Dale"}); + c = Car.findOne(doc._id); -c.set("plate", {code: "BASFACE"}); + c.manufacturer({name: "Audi", location: "Germany"}); -c.windows.add([ - {type: "windshield"}, - {type: "frontDriver"}, - {type: "frontPassenger"}, - {type: "rear"} -]); + c.wheels.add({}); + c.wheels.add([{}, {tread: 'worn'}, {}]); + w = Wheel.build({}); + w.save(); + w.set("isFlat", true); + w.save(); + c.drivers.add({name: "Mario"}); + c.drivers.add({name: "Dale"}); + c.set("plate", {code: "BASFACE"}); + c.windows.add([ + {type: "windshield"}, + {type: "frontDriver"}, + {type: "frontPassenger"}, + {type: "rear"} + ]); +}; +//////////////////// +setup(); Tinytest.add('Model - initialize', function(test) { + setup(); test.equal(c.get('price'), 98); test.equal(c._collection._name, 'cars'); test.equal(doc.color, c.attributes.color); @@ -141,34 +152,43 @@ Tinytest.add('Model - initialize', function(test) { }); Tinytest.add('Model - defaults', function(test) { + setup(); test.equal(w.get("tread"), "new"); }); Tinytest.add('Model - save', function(test) { + setup(); test.equal(_.isString(w._id), true); var flat = Wheel.findOne({isFlat: true}); test.equal((flat instanceof Graviton.Model), true); }); Tinytest.add('Relations - hasMany', function(test) { + setup(); test.equal(c.wheels._collection._name, 'wheels'); test.equal(c.wheels.find().count(), 4); test.equal(c.wheels.all().length, c.wheels.find().count()); test.equal(c.wheels.find({tread: 'new'}).count(), 3); - test.equal(Driver.findOne().cars.findOne()._id, c._id); + test.equal(c.drivers.findOne().cars.find().count(), 1); }); Tinytest.add('Relations - hasOne', function(test) { + setup(); test.isTrue(c.manufacturer() instanceof Graviton.Model); - var mfr = Mfr.findOne(); + var mfr = Mfr.findOne({carId: c._id}); test.equal(mfr._id, c.manufacturer()._id); }); Tinytest.add('Relations - belongsTo', function(test) { + setup(); test.equal(c.wheels.findOne().car()._id, c._id); }); Tinytest.add('Relations - belongsToMany', function(test) { + setup(); + if (c.drivers.find().count() != 2) { + console.log(c.drivers.find().fetch()); + } test.equal(c.drivers.find().count(), 2); test.equal(_.isArray(c.get("driverIds")), true); @@ -187,16 +207,51 @@ Tinytest.add('Relations - belongsToMany', function(test) { var d = c.drivers.findOne(); var cur = c.drivers.find({_id: {$ne: d._id}}); test.equal(cur.count(), 2); + }); Tinytest.add('Relations - embeds', function(test) { + setup(); test.isTrue(c.plate() instanceof Graviton.Model); test.equal(c.plate().get("code"), "BASFACE"); }); Tinytest.add('Relations - embedsMany', function(test) { + setup(); test.isTrue(c.windows.at(0) instanceof Graviton.Model); test.equal(c.windows.all().length, 4); test.equal(c.windows.at(2).get("type"), "frontPassenger"); test.equal(c.get("windows").length, 4); }); + + +//////// + +var Mdl = Graviton.Model.extend({}); +var SubMdl = Mdl.extend({}); + +var Raw = Graviton.define('raw', {persist: false}); +var Col = Graviton.define('col', {modelCls: Mdl, persist: false}); +var SubCol = Graviton.define('sub', {modelCls: SubMdl, persist: false}); + +var r = Raw.build({}); +var m = Col.build({}); +var s = SubCol.build({}); + + +Tinytest.add('Model - isModel', function(test) { + test.isTrue(Graviton.isModel(r)); + test.isTrue(Graviton.isModel(m)); + test.isTrue(Graviton.isModel(s)); + test.isFalse(Graviton.isModel({})); + test.isFalse(Graviton.isModel([])); + test.isFalse(Graviton.isModel("xxx")); + test.isFalse(Graviton.isModel(234)); + test.isFalse(Graviton.isModel(_)); + test.isFalse(Graviton.isModel(Graviton)); +}); + + + + +