-
Notifications
You must be signed in to change notification settings - Fork 6
/
ampersand-collection-underscore-mixin.js
65 lines (56 loc) · 2.15 KB
/
ampersand-collection-underscore-mixin.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
/*$AMPERSAND_VERSION*/
var _ = require('underscore');
var slice = [].slice;
var mixins = {};
// Underscore methods that we want to implement on the Collection.
var methods = ['forEach', 'each', 'map', 'collect', 'reduce', 'foldl',
'inject', 'reduceRight', 'foldr', 'find', 'detect', 'filter', 'select',
'reject', 'every', 'all', 'some', 'any', 'include', 'contains', 'invoke',
'max', 'min', 'toArray', 'size', 'first', 'head', 'take', 'initial', 'rest',
'tail', 'drop', 'last', 'without', 'difference', 'indexOf', 'shuffle',
'lastIndexOf', 'isEmpty', 'chain', 'sample', 'partition'
];
// Mix in each Underscore method as a proxy to `Collection#models`.
_.each(methods, function (method) {
if (!_[method]) return;
mixins[method] = function () {
var args = slice.call(arguments);
args.unshift(this.models);
return _[method].apply(_, args);
};
});
// Underscore methods that take a property name as an argument.
var attributeMethods = ['groupBy', 'countBy', 'sortBy', 'indexBy'];
// Use attributes instead of properties.
_.each(attributeMethods, function (method) {
if (!_[method]) return;
mixins[method] = function (value, context) {
var iterator = _.isFunction(value) ? value : function (model) {
return model.get ? model.get(value) : model[value];
};
return _[method](this.models, iterator, context);
};
});
// Return models with matching attributes. Useful for simple cases of
// `filter`.
mixins.where = function (attrs, first) {
if (_.isEmpty(attrs)) return first ? void 0 : [];
return this[first ? 'find' : 'filter'](function (model) {
var value;
for (var key in attrs) {
value = model.get ? model.get(key) : model[key];
if (attrs[key] !== value) return false;
}
return true;
});
};
// Return the first model with matching attributes. Useful for simple cases
// of `find`.
mixins.findWhere = function (attrs) {
return this.where(attrs, true);
};
// Plucks an attribute from each model in the collection.
mixins.pluck = function (attr) {
return _.invoke(this.models, 'get', attr);
};
module.exports = mixins;