diff --git a/packages/minimongo/minimongo.js b/packages/minimongo/minimongo.js index 6d920b26fb..8d161fdad6 100644 --- a/packages/minimongo/minimongo.js +++ b/packages/minimongo/minimongo.js @@ -156,6 +156,7 @@ LocalCollection.Cursor.prototype.forEach = function (callback) { }; LocalCollection.Cursor.prototype.getFactory = function () { + var self = this; return self._factory; }; diff --git a/packages/mongo-livedata/mongo_driver.js b/packages/mongo-livedata/mongo_driver.js index e522d5ba4c..f7ecd9b39f 100644 --- a/packages/mongo-livedata/mongo_driver.js +++ b/packages/mongo-livedata/mongo_driver.js @@ -362,6 +362,7 @@ var Cursor = function (mongo, cursorDescription) { self._mongo = mongo; self._cursorDescription = cursorDescription; + if (cursorDescription.options.factory) self._synchronousCursor = null; }; @@ -455,11 +456,14 @@ _Mongo.prototype._createSynchronousCursor = function (cursorDescription) { if (!result[0]) throw result[1]; - return new SynchronousCursor(result[1]); + return new SynchronousCursor(result[1], + cursorDescription.options && + cursorDescription.options.factory); }; -var SynchronousCursor = function (dbCursor) { +var SynchronousCursor = function (dbCursor, factory) { var self = this; + self._factory = factory; self._dbCursor = dbCursor; // Need to specify that the callback is the first argument to nextObject, // since otherwise when we try to call it with no args the driver will @@ -477,6 +481,8 @@ _.extend(SynchronousCursor.prototype, { var doc = self._synchronousNextObject().wait(); if (!doc || !doc._id) return null; doc = replaceTypes(doc, replaceMongoAtomWithMeteor); + if (self._factory) + doc = self._factory(doc); var strId = Meteor.idStringify(doc._id); if (self._visitedIds[strId]) continue; self._visitedIds[strId] = true; diff --git a/packages/mongo-livedata/mongo_livedata_tests.js b/packages/mongo-livedata/mongo_livedata_tests.js index d6ede91ea0..a481bd2e1f 100644 --- a/packages/mongo-livedata/mongo_livedata_tests.js +++ b/packages/mongo-livedata/mongo_livedata_tests.js @@ -3,10 +3,13 @@ (function () { //var Future = __meteor_bootstrap__.require('fibers/future'); - +var FACTORIES = {}; if (Meteor.isServer) { Meteor.methods({ createInsecureCollection: function (name, options) { + if (options && options.defaultFactoryName) { + options.defaultFactory = FACTORIES[options.defaultFactoryName]; + } var c = new Meteor.Collection(name, options); c._insecure = true; Meteor.publish('c-' + name, function () { @@ -625,6 +628,37 @@ testAsyncMulti('mongo-livedata - document with a date, ' + idGeneration, [ } ]); +testAsyncMulti('mongo-livedata - document goes through a factory, ' + idGeneration, [ + function (test, expect) { + var seconds = function (doc) { + doc.seconds = function () {return doc.d.getSeconds();}; + return doc; + }; + FACTORIES["seconds"] = seconds; + var collectionOptions = { + idGeneration: idGeneration, + defaultFactory: seconds, + defaultFactoryName: "seconds" + }; + var collectionName = Random.id(); + if (Meteor.isClient) { + Meteor.call('createInsecureCollection', collectionName, collectionOptions); + Meteor.subscribe('c-' + collectionName); + } + + var coll = new Meteor.Collection(collectionName, collectionOptions); + var docId; + coll.insert({d: new Date(1356152390004)}, expect(function (err, id) { + test.isFalse(err); + test.isTrue(id); + docId = id; + var cursor = coll.find(); + test.equal(cursor.count(), 1); + test.equal(coll.findOne().seconds(), 50); + })); + } +]); + testAsyncMulti('mongo-livedata - document with binary data, ' + idGeneration, [ function (test, expect) { var bin = EJSON._base64Decode( diff --git a/packages/spark/spark.js b/packages/spark/spark.js index 9736565100..9fb05119af 100644 --- a/packages/spark/spark.js +++ b/packages/spark/spark.js @@ -988,7 +988,12 @@ Spark.list = function (cursor, itemFunc, elseFunc) { later(function () { var doc = EJSON.clone(fields); doc._id = id; - var frag = Spark.render(_.bind(itemFunc, null, doc)); + var renderDoc = doc; + if (cursor.getFactory && cursor.getFactory()) { + console.log(cursor.getFactory()); + renderDoc = EJSON.clone(renderDoc); + } + var frag = Spark.render(_.bind(itemFunc, null, renderDoc)); DomUtils.wrapFragmentForContainer(frag, outerRange.containerNode()); var range = makeRange(Spark._ANNOTATION_LIST_ITEM, frag); @@ -1038,7 +1043,10 @@ Spark.list = function (cursor, itemFunc, elseFunc) { if (!elt) throw new Error("Unknown id for changed: " + id); applyChanges(elt.doc, fields); - Spark.renderToRange(elt.liveRange, _.bind(itemFunc, null, elt.doc)); + var renderDoc = elt.doc; + if (cursor.getFactory && cursor.getFactory()) + renderDoc = cursor.getFactory()(EJSON.clone(elt.doc)); + Spark.renderToRange(elt.liveRange, _.bind(itemFunc, null, renderDoc)); }); } });