/lib/collections/base-collection.js
https://bitbucket.org/madebybottle/bottlecap · JavaScript · 143 lines · 96 code · 23 blank · 24 comment · 21 complexity · a99e0b2eb4dbde6717ad1f49affd5ba3 MD5 · raw file
- module.exports = function(options) {
- // ## BaseCollection
- // -----------------
- // The BaseCollection is the base Collection for storing instances of models
- // for Bottlecap. It is the same as a normal Backbone.Collection, but with
- // a few alterations:
- //
- // - It keeps a reference to the event bus upon construction
- // - It can reply to DataStore API requests on that event bus, if a
- // namespace option is passed to it.
- // ### Dependencies
- // ----------------
- var Backbone = options.Backbone;
- var _ = options._;
- var FilterCollection = options.FilterCollection;
- // ### BaseCollection
- // ------------------
- var BaseCollection = Backbone.Collection.extend({
- // The DataStore API events
- dataStoreAPI: [
- 'all', 'find', 'where', 'filter', 'build'
- ],
- // Creates a BaseCollection and returns it. Accepts `models`, and
- // `options` parameters. The `options` parameter should contain an
- // instance of the application event bus. If you want this BaseCollection
- // to be able to respond to DataStore API requests on the event bus, you
- // should also pass a `namespace` property on the `options` object.
- constructor: function(models, options) {
- Backbone.Collection.apply(this, arguments);
- models = models || [];
- options = options || {};
- this._vent = options.vent;
- if (!this.namespace) {
- this.namespace = options.namespace;
- }
- if (this.namespace) {
- var locals = _.map(this.dataStoreAPI, function(name) {
- return '_' + name;
- });
- _.bindAll(this, locals);
- this._setupDSBindings(this.namespace, this.dataStoreAPI);
- }
- return this;
- },
- // ### DataStore API functions
- _subcollection: function(options) {
- var col = new FilterCollection({
- filter: options.filter,
- parent: this
- });
- return col;
- },
- _build: function(attrs, options, cb) {
- var args = Array.prototype.slice.call(arguments);
- if (args.length === 1) {
- cb = args[0];
- attrs = {};
- options = {};
- } else if (args.length === 2) {
- attrs = args[0];
- options = {};
- cb = args[1];
- }
- var model = new this.model(attrs, options);
- return cb (null, model);
- },
- _all: function(cb) {
- var filter = function(model) { return true; };
- var all = this._subcollection({filter: filter});
- return cb(null, all);
- },
- _find: function(attrs, cb) {
- this._where(attrs, function(err, data) {
- if (err) { return cb(err); }
- if (data.length < 1) {
- err = new Error('DSNotFoundError');
- return cb(err);
- }
- var model = data.at(0);
- return cb(null, model);
- });
- },
- _where: function(attrs, cb) {
- var filter = function(model) {
- for (var key in attrs) {
- var modelValue = model.get(key);
- var value = attrs[key];
- if ((value instanceof Array) && (modelValue instanceof Array)) {
- if (value !== modelValue) { return false; }
- } else if (value instanceof Array) {
- if (!_.contains(value, modelValue)) { return false; }
- } else if (modelValue instanceof Array) {
- if (!_.contains(modelValue, value)) { return false; }
- } else {
- if (modelValue !== value) { return false; }
- }
- }
- return true;
- };
- var col = this._subcollection({filter: filter});
- return cb(null, col);
- },
- _filter: function(filter, cb) {
- var col = this._subcollection({filter: filter});
- return cb(null, col);
- },
- // Binds DataStore API message names to functions on this instance. For
- // example, ds:contacts:all -> this._all
- _setupDSBindings: function(namespace, dsEvents) {
- _.each(dsEvents, function(name) {
- var messageName = 'ds:' + namespace + ':' + name;
- var ourFunc = this['_' + name];
- this._vent.handle(messageName, ourFunc);
- }, this);
- }
- });
- // ### Exports
- // -----------
- return BaseCollection;
- };