Filtering Backbone Collections
- 12/9/2012
- ·
- #index
Some data-heavier Backbone projects have gotten me to thinking a bit about how Backbone collections are organized. On the one hand, it’s hard to argue with the tidy syntax used to operate on a set of models:
var names = myCollection.map(function (model) {
return model.get('name');
});
On the other hand, it tends to breed one-off closures that rarely exist past the immediate scope. Iterators are small things–trivial, even–and it’s just as easy to re-write them off as to store them for re-use. That’s Problem One.
The second problem is my own laziness. I would obviously prefer to reuse collection operations rather than re-authoring them, but what would really be great is if I could take a bunch of filters and start stringing them together to solve more complicated problems.
Take one implemented filtering as a wrapper for a given collection (in 20/20 hindsight, there’s a nice project on github that does this much better), but I ended up focused much more on the collection than on the actual filtering code.
Looking to angular for inspiration, I’ve started dressing up filters into nice, variable chunks (spoiler alert: github repo here). The general idea is to provide a base interface–Backbone.Filter
–that can be extended to perform all kinds of collection operations. The children of this interface can then be instantiated with specific parameters and re-used throughout a project. For instance, we might create filters based on the underscore shuffle
and first
methods:
var random = new Backbone.Filter.shuffle,
limit3 = new Backbone.Filter.first(3);
We could then apply these to a collection to choose three models at random. Shuffle it, choose three.
var pick3 = myCollection.filter(random).filter(limit3);
To make things really easy, each filter is set up to return a new collection with the models that were chosen by the previous filter. So instead of three models, pick3
now contains a Collection
with three random models from myCollection
.
But we’re lazy, remember? To make things even simpler, why not extend the filter
method to support an array of filters? Getting three models at random is now as simple as:
pick3 = myCollection.filter([random, limit3]);
In this notation, the output of each filter will be used as the input to the next. The formats must match: a filter that reduced a collection to an array of attribute values, for instance could not come before one expecting a full collection:
var names = new Backbone.Filter.map(function (m) {
return m.get('name');
});
// this doesn't work
myCollection.filter([names, random]);
// but this does
myCollection.filter([random, names]);
Anyway. I haven’t gotten enough reps in yet to determine its actual utility, but I did throw together a small github project for review. Floor’s open. Comments? Thoughts?