PageRenderTime 46ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/node_modules/bookshelf/dialects/base/collection.js

https://github.com/bluephlame/resolvingdad
JavaScript | 175 lines | 111 code | 34 blank | 30 comment | 35 complexity | 76b5b8d3ed58b0dfd868bcaf05e0c2fc MD5 | raw file
Possible License(s): MIT, BSD-2-Clause, Apache-2.0, JSON, 0BSD, BSD-3-Clause
  1. // Base Collection
  2. // ---------------
  3. (function(define) {
  4. "use strict";
  5. // The `CollectionBase` is an object that takes
  6. define(function(require, exports) {
  7. // All exernal dependencies required in this scope.
  8. var _ = require('lodash');
  9. var Backbone = require('backbone');
  10. // All components that need to be referenced in this scope.
  11. var Events = require('./events').Events;
  12. var Promise = require('./promise').Promise;
  13. var ModelBase = require('./model').ModelBase;
  14. var array = [];
  15. var push = array.push;
  16. var splice = array.splice;
  17. var CollectionBase = function(models, options) {
  18. if (options) _.extend(this, _.pick(options, collectionProps));
  19. this._reset();
  20. this.initialize.apply(this, arguments);
  21. if (models) this.reset(models, _.extend({silent: true}, options));
  22. };
  23. // List of attributes attached directly from the constructor's options object.
  24. var collectionProps = ['model', 'comparator'];
  25. // A list of properties that are omitted from the `Backbone.Model.prototype`, to create
  26. // a generic collection base.
  27. var collectionOmitted = ['model', 'fetch', 'url', 'sync', 'create'];
  28. // Copied over from Backbone.
  29. var setOptions = {add: true, remove: true, merge: true};
  30. _.extend(CollectionBase.prototype, _.omit(Backbone.Collection.prototype, collectionOmitted), Events, {
  31. // The `tableName` on the associated Model, used in relation building.
  32. tableName: function() {
  33. return _.result(this.model.prototype, 'tableName');
  34. },
  35. // The `idAttribute` on the associated Model, used in relation building.
  36. idAttribute: function() {
  37. return this.model.prototype.idAttribute;
  38. },
  39. // A simplified version of Backbone's `Collection#set` method,
  40. // removing the comparator, and getting rid of the temporary model creation,
  41. // since there's *no way* we'll be getting the data in an inconsistent
  42. // form from the database.
  43. set: function(models, options) {
  44. options = _.defaults({}, options, setOptions);
  45. if (options.parse) models = this.parse(models, options);
  46. if (!_.isArray(models)) models = models ? [models] : [];
  47. var i, l, id, model, attrs, existing;
  48. var at = options.at;
  49. var targetModel = this.model;
  50. var toAdd = [], toRemove = [], modelMap = {};
  51. var add = options.add, merge = options.merge, remove = options.remove;
  52. var order = add && remove ? [] : false;
  53. // Turn bare objects into model references, and prevent invalid models
  54. // from being added.
  55. for (i = 0, l = models.length; i < l; i++) {
  56. attrs = models[i];
  57. if (attrs instanceof ModelBase) {
  58. id = model = attrs;
  59. } else {
  60. id = attrs[targetModel.prototype.idAttribute];
  61. }
  62. // If a duplicate is found, prevent it from being added and
  63. // optionally merge it into the existing model.
  64. if (existing = this.get(id)) {
  65. if (remove) {
  66. modelMap[existing.cid] = true;
  67. continue;
  68. }
  69. if (merge) {
  70. attrs = attrs === model ? model.attributes : attrs;
  71. if (options.parse) attrs = existing.parse(attrs, options);
  72. existing.set(attrs, options);
  73. }
  74. // This is a new model, push it to the `toAdd` list.
  75. } else if (add) {
  76. if (!(model = this._prepareModel(attrs, options))) continue;
  77. toAdd.push(model);
  78. // Listen to added models' events, and index models for lookup by
  79. // `id` and by `cid`.
  80. model.on('all', this._onModelEvent, this);
  81. this._byId[model.cid] = model;
  82. if (model.id != null) this._byId[model.id] = model;
  83. }
  84. if (order) order.push(existing || model);
  85. }
  86. // Remove nonexistent models if appropriate.
  87. if (remove) {
  88. for (i = 0, l = this.length; i < l; ++i) {
  89. if (!modelMap[(model = this.models[i]).cid]) toRemove.push(model);
  90. }
  91. if (toRemove.length) this.remove(toRemove, options);
  92. }
  93. // See if sorting is needed, update `length` and splice in new models.
  94. if (toAdd.length || (order && order.length)) {
  95. this.length += toAdd.length;
  96. if (at != null) {
  97. splice.apply(this.models, [at, 0].concat(toAdd));
  98. } else {
  99. if (order) this.models.length = 0;
  100. push.apply(this.models, order || toAdd);
  101. }
  102. }
  103. if (options.silent) return this;
  104. // Trigger `add` events.
  105. for (i = 0, l = toAdd.length; i < l; i++) {
  106. (model = toAdd[i]).trigger('add', model, this, options);
  107. }
  108. return this;
  109. },
  110. // Prepare a model or hash of attributes to be added to this collection.
  111. _prepareModel: function(attrs, options) {
  112. if (attrs instanceof ModelBase) return attrs;
  113. return new this.model(attrs, options);
  114. },
  115. // Convenience method for map, returning a `Promise.all` promise.
  116. mapThen: function(iterator, context) {
  117. return Promise.all(this.map(iterator, context));
  118. },
  119. // Convenience method for invoke, returning a `Promise.all` promise.
  120. invokeThen: function() {
  121. return Promise.all(this.invoke.apply(this, arguments));
  122. },
  123. fetch: function() {
  124. return Promise.rejected('The fetch method has not been implemented');
  125. },
  126. _handleResponse: function() {},
  127. _handleEager: function() {}
  128. });
  129. // List of attributes attached directly from the `options` passed to the constructor.
  130. var modelProps = ['tableName', 'hasTimestamps'];
  131. CollectionBase.extend = Backbone.Collection.extend;
  132. // Helper to mixin one or more additional items to the current prototype.
  133. CollectionBase.include = function() {
  134. _.extend.apply(_, [this.prototype].concat(_.toArray(arguments)));
  135. return this;
  136. };
  137. exports.CollectionBase = CollectionBase;
  138. });
  139. })(
  140. typeof define === 'function' && define.amd ? define : function (factory) { factory(require, exports); }
  141. );