diff --git a/.versions b/.versions index 6f4985d..8a2d59c 100644 --- a/.versions +++ b/.versions @@ -6,33 +6,33 @@ blaze@2.1.3 blaze-tools@1.0.4 boilerplate-generator@1.0.4 callback-hook@1.0.4 -check@1.0.6 -dburles:collection-helpers@1.0.4 +check@1.1.0 ddp@1.2.2 ddp-client@1.2.1 -ddp-common@1.2.1 -ddp-server@1.2.1 +ddp-common@1.2.2 +ddp-server@1.2.2 deps@1.0.9 diff-sequence@1.0.1 -ecmascript@0.1.5 -ecmascript-collections@0.1.6 +ecmascript@0.1.6 +ecmascript-runtime@0.2.6 ejson@1.0.7 +ephemer:collection-helpers@1.1.0 geojson-utils@1.0.4 html-tools@1.0.5 htmljs@1.0.5 id-map@1.0.4 jquery@1.11.4 -local-test:dburles:collection-helpers@1.0.4 +local-test:ephemer:collection-helpers@1.1.0 logging@1.0.8 -meteor@1.1.9 +meteor@1.1.10 minimongo@1.0.10 -mongo@1.1.2 +mongo@1.1.3 mongo-id@1.0.1 npm-mongo@1.4.39_1 observe-sequence@1.0.7 ordered-dict@1.0.4 -promise@0.5.0 -random@1.0.4 +promise@0.5.1 +random@1.0.5 reactive-var@1.0.6 retry@1.0.4 routepolicy@1.0.6 @@ -42,5 +42,5 @@ tinytest@1.0.6 tracker@1.0.9 ui@1.0.8 underscore@1.0.4 -webapp@1.2.2 +webapp@1.2.3 webapp-hashing@1.0.5 diff --git a/README.md b/README.md index 9cc4639..f1b0911 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Collection helpers automatically sets up a transformation on your collections us ## Installation ```sh -$ meteor add dburles:collection-helpers +$ meteor add ephemer:collection-helpers ``` ## Usage diff --git a/collection-helpers.js b/collection-helpers.js index 47c1c74..0edc671 100644 --- a/collection-helpers.js +++ b/collection-helpers.js @@ -1,18 +1,47 @@ Mongo.Collection.prototype.helpers = function(helpers) { - var self = this; + let self = this; - if (self._transform && ! self._helpers) - throw new Meteor.Error("Can't apply helpers to '" + - self._name + "' a transform function already exists!"); + if (!self._helpers) { + let OriginalDocument = class OriginalDocument {}; - if (! self._helpers) { - self._helpers = function Document(doc) { return _.extend(this, doc); }; - self._transform = function(doc) { - return new self._helpers(doc); - }; - } + if (self._transform) { + let transformedDoc = createDummyTransformedDocument.call(self); + OriginalDocument = transformedDoc.__proto__.constructor; + if (OriginalDocument === Object) { + OriginalDocument = self._transform; + } + } - _.each(helpers, function(helper, key) { - self._helpers.prototype[key] = helper; - }); + self._helpers = class DocumentWithHelpers extends OriginalDocument { + constructor(doc) { + super(doc); + return _.extend(this, doc); + } + } + + self._transform = function(doc) { + return new self._helpers(doc); + }; + } + + let transformedDoc = createDummyTransformedDocument.call(self); + _.each(helpers, function(helper, key) { + if (transformedDoc[key] === undefined) { + self._helpers.prototype[key] = helper; + } else { + throw new Meteor.Error(`A helper called ${key} already exists on ${self}`) + } + }); }; + + +function createDummyTransformedDocument() { + try { + return this._transform({_id: 'fakeDocument'}); + } catch(e) { + throw new Meteor.Error(`Error while adding helpers to your Collection`, + `This only happens when your Collection has an existing transform + that accesses non-initialised state internally and then you try to + add helpers via Collection.helpers({}).`) + } +} diff --git a/collection-helpers_tests.js b/collection-helpers_tests.js index 0d2f595..3f03c85 100644 --- a/collection-helpers_tests.js +++ b/collection-helpers_tests.js @@ -1,74 +1,156 @@ -Tinytest.add("works", function(test) { - Books = new Mongo.Collection('books' + test.id); - Authors = new Mongo.Collection('authors' + test.id); - - var author1 = Authors.insert({ - firstName: 'Charles', - lastName: 'Darwin' - }); - - var author2 = Authors.insert({ - firstName: 'Carl', - lastName: 'Sagan' - }); - - var book1 = Books.insert({ - authorId: author1, - name: 'On the Origin of Species' - }); - - var book2 = Books.insert({ - authorId: author2, - name: 'Contact' - }); - - Books.helpers({ - author: function() { - return Authors.findOne(this.authorId); +'use strict'; + +Tinytest.add("Works as expected in base case", function(test) { + var Books = new Mongo.Collection(null); + var Authors = new Mongo.Collection(null); + + var author1 = Authors.insert({ + firstName: 'Charles', + lastName: 'Darwin' + }); + + var author2 = Authors.insert({ + firstName: 'Carl', + lastName: 'Sagan' + }); + + var book1 = Books.insert({ + authorId: author1, + name: 'On the Origin of Species' + }); + + var book2 = Books.insert({ + authorId: author2, + name: 'Contact' + }); + + Books.helpers({ + author: function() { + return Authors.findOne(this.authorId); + } + }); + + // We should be able to apply more if we wish + Books.helpers({ + foo: 'bar' + }); + + Authors.helpers({ + fullName: function() { + return this.firstName + ' ' + this.lastName; + }, + books: function() { + return Books.find({ authorId: this._id }); + } + }); + + var book = Books.findOne(book1); + var author = book.author(); + + test.equal(author.firstName, 'Charles'); + test.equal(book.foo, 'bar'); + + book = Books.findOne(book2); + author = book.author(); + test.equal(author.fullName(), 'Carl Sagan'); + + author = Authors.findOne(author1); + var books = author.books(); + test.equal(books.count(), 1); +}); + +Tinytest.add("Throw error if transform function already exists", function(test) { + class Author { + constructor(doc) { + return _.extend(this, doc); + } + + fullName() { + return 'Charles Darwin'; + } } - }); - - // We should be able to apply more if we wish - Books.helpers({ - foo: 'bar' - }); - - Authors.helpers({ - fullName: function() { - return this.firstName + ' ' + this.lastName; - }, - books: function() { - return Books.find({ authorId: this._id }); + + var Authors = new Meteor.Collection(null, { + transform(doc) { + return new Author(doc); + } + }); + + test.throws(function() { + Authors.helpers({ + fullName() { + return this.firstName + ' ' + this.lastName; + } + }); + }); +}); + +Tinytest.add("Work normally if non-conflicting transform function already exists", function(test) { + class Author { + constructor(doc) { + return _.extend(this, doc); + } + + aSmartMan() { + return 'Charles Darwin'; + } } - }); - var book = Books.findOne(book1); - var author = book.author(); - test.equal(author.firstName, 'Charles'); - test.equal(book.foo, 'bar'); + var Authors = new Meteor.Collection(null, { + transform(doc) { + return new Author(doc); + } + }); - book = Books.findOne(book2); - author = book.author(); - test.equal(author.fullName(), 'Carl Sagan'); + Authors.helpers({ + fullName() { + return this.firstName + ' ' + this.lastName; + } + }); - author = Authors.findOne(author1); - books = author.books(); - test.equal(books.count(), 1); -}); + Authors.insert({ + firstName: 'Charles', + lastName: 'Darwin' + }); -Tinytest.add("throw error if transform function already exists", function(test) { - Author = function(doc) { return _.extend(this, doc); }; + let author = Authors.findOne(); + test.equal(author.fullName(), author.aSmartMan()); +}); - Author.prototype.fullName = 'Charles Darwin'; - Authors = new Meteor.Collection('authors' + test.id, { - transform: function(doc) { return new Author(doc); }}); +Tinytest.add("Use a normal transform too without breaking things", function(test) { + var Authors = new Meteor.Collection(null, { + transform(doc) { + doc.normalTransform = 'working'; + return doc; + } + }); - test.throws(function() { Authors.helpers({ - fullName: function() { - return this.firstName + ' ' + this.lastName; - } + fullName() { + return this.firstName + ' ' + this.lastName; + } }); - }); -}); \ No newline at end of file + + Authors.insert({ + firstName: 'Bob', + lastName: 'Dole' + }); + + let bob = Authors.findOne(); + + test.equal(bob.firstName, 'Bob'); + test.equal(bob.lastName, 'Dole'); + test.equal(bob.fullName(), 'Bob Dole'); + test.equal(bob.normalTransform, 'working'); + + test.throws(function() { + Authors.helpers({ + normalTransform() { + return "This should fail"; + } + }); + }); + + test.equal(bob.normalTransform, 'working'); +}); diff --git a/package.js b/package.js index 0201942..418c502 100644 --- a/package.js +++ b/package.js @@ -1,25 +1,27 @@ Package.describe({ - name: "dburles:collection-helpers", - summary: "Transform your collections with helpers that you define", - version: "1.0.4", - documentation: "README.md", - git: "https://github.com/dburles/meteor-collection-helpers.git", + name: "ephemer:collection-helpers", + summary: "Transform Collections with self-defined helpers. Works with TAPi18n & other self-defined transforms!", + version: "1.1.0", + documentation: "README.md", + git: "https://github.com/ephemer/meteor-collection-helpers.git", }); Package.onUse(function(api) { - api.versionsFrom('1.2.0.2'); - api.use([ - 'underscore', - 'mongo']); + api.versionsFrom('1.2.0.2'); + api.use([ + 'ecmascript', + 'underscore', + 'mongo']); - api.addFiles('collection-helpers.js'); + api.addFiles('collection-helpers.js'); }); Package.onTest(function(api) { - api.use([ - 'tinytest', - 'underscore', - 'mongo', - 'dburles:collection-helpers']); - api.addFiles('collection-helpers_tests.js'); + api.use([ + 'ecmascript', + 'tinytest', + 'underscore', + 'mongo', + 'ephemer:collection-helpers']); + api.addFiles('collection-helpers_tests.js'); });