Skip to content

Instantly share code, notes, and snippets.

@wearhere
Last active August 29, 2015 14:21
Show Gist options
  • Save wearhere/c87d181868dc3d4c1866 to your computer and use it in GitHub Desktop.
Save wearhere/c87d181868dc3d4c1866 to your computer and use it in GitHub Desktop.
Backbone.MeteorCollection, a subclass of Backbone.Collection that updates from a Meteor collection using https://gist.github.com/wearhere/acf71ceba51a2e77c8ec. More info and examples at https://mixmax.com/blog/meteor-and-backbone.
Backbone.MeteorCollection = Backbone.Collection.extend({
_reactiveQuery: null,
_waitOn: null,
/**
* @param {object} options
* @property {ReactiveQuery} reactiveQuery - The query to observe.
* @property {Subscription=} waitOn - (Optional) A subscription whose record set corresponds to
* _reactiveQuery_. If specified, the collection will wait until the subscription becomes ready
* before beginning to observe the query. This avoids emitting 'add' events for every record
* in the initial set; rather, the collection will reset itself to the query's result set
* (and emit a single 'reset' event) when the subscription becomes ready.
*/
initialize: function(models, options) {
if (!(this.model.prototype instanceof Backbone.MeteorModel)) {
throw 'MeteorCollection models must derive from MeteorModel for syncing to work right.';
}
this._reactiveQuery = options.reactiveQuery;
this._waitOn = options.waitOn;
if (this._waitOn) {
this._waitOn.whenReady().then(function() {
// Once the relevant subscription is ready, reset the collection to the current state of the
// result set. (We've skipped over the initial 'add' events.)
this.reset(this._reactiveQuery.fetch());
this._beginObservingChanges();
}.bind(this));
} else {
this._beginObservingChanges();
}
},
_beginObservingChanges: function() {
this._reactiveQuery
.on('added', function(id, fields) {
var doc = _.extend({ _id: id }, fields);
// If the collection was not instructed to wait for the relevant subscription to become ready,
// this will be called for the initial result set. Since that may overlap with the models
// with which the collection was initialized, we merge the models.
this.add(doc, { merge: true });
}, this)
.on('changed', function(id, fields) {
var model = this.get(id);
if (model) {
var toUnset = _.pick(fields, _.isUndefined);
model.unset(toUnset);
var toSet = _.omit(fields, _.isUndefined);
model.set(toSet);
}
}, this)
.on('removed', function(id) {
var model = this.get(id);
if (model) {
this.remove(model);
}
}, this);
}
});
Backbone.MeteorModel = Backbone.Model.extend({
idAttribute: '_id'
});
@wearhere
Copy link
Author

This will be renamed/polished/packaged as a full-fledge open-source project soon. In the meantime, this requires:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment