I'm learning javascript, angular and Parse.com all at once, and it's going well, but my learning app is getting a little more complex, and I'm not sure how to proceed. I've built some model logic that makes Parse play well with Angular, but I'm starting to see problems with it, and wondering whether I should abandon it for another approach.
For simplicity let's say my model is (the typical) Post with many Comments. I found some net code that I thought did a good job wrapping Parse.com objects, like this:
var module = angular.module('myApp.services');
module.factory('Post', function(Comment) {
// I defined Comment service just like this and inject it here (will explain why below)
var Post = Parse.Object.extend("Post", {
// instance methods
}, {
// class methods
});
// properties
_.each(["title", "content", "etc"], function(col) {
Object.defineProperty(Post.prototype, col, {
get: function() {return this.get(col);},
set: function(aValue) {this.set(col, aValue);}
});
});
return Post;
});
This provides properties to match the scalar attributes of my Parse model. But Posts have Comments, and, in my app, I'll need to use parts of the comments as ng-model in a detail view.
If I just add "comments" to the list of properties to define, the resulting array contains the native Parse objects, not wrapped for Angular. So I added this new paragraph as follows:
// relational properties 1-n
_.each([[Comment, "comments"] /* here I would list other 1-n relations */], function(col) {
var cacheKey = 'cached'+col[1];
Object.defineProperty(Post.prototype, cacheKey, { enumerable: true, writable: true });
Object.defineProperty(Post.prototype, col[1], {
get: function() {
if (this[cacheKey] === undefined) {
var raw = this.get(col[1]);
var klass = col[0];
this[cacheKey] = _.map(raw, function(each) { return new klass(each); });
}
return this[cacheKey];
}
});
});
I did this half-blind, borrowing examples of defineProperty
from SO. I had to add a property for each called cached*colname* otherwise I'd end up re-creating objects on each get. This is wasteful and it makes Angular angry because I guess ng-repeat expects successive gets to return the same list.
So I'm starting to see problems with this idea:
- I don't see how the set can work or how updated comments can be saved. I think I'll have to override the Parse save method to set the real original comments property.
- I just realized that for this to work, all the queries I write as class methods are going to have to eagerly .include("comments"). I think I'll have to make a promise-returning version of the getters. Yikes.
- There's probably some worse gotchas having to do with defineProperty. It's my first time doing any of this.
Am I right about these problems? Should I pursue fixing these, or is whole approach a rabbit hole I'm going to wish I didn't run down?