I have a collection, which fetches data from URL.
BarCollection = Backbone.Collection.extend({
model: BarModel,
url: // Some URL
});
But the problem is that I want to fetch data to this collection not only from URL, but also from local storage. I wish I could do something like that:
BarCollection = Backbone.Collection.extend({
model: BarModel,
url: // Some URL,
localStorage: new Backbone.LocalStorage('bars')
});
But .fetch()
method cannot get data both from url and local storage.
Simple workaround is to create two different collections: one for URL and one for local storage. And after fetching just merge them.
BarCollection = Backbone.Collection.extend({
model: BarModel,
url: // Some URL
});
LocalBarCollection = Backbone.Collection.extend({
model: BarModel,
localStorage: new Backbone.LocalStorage('local-contributors')
});
I wonder if there is a more beautiful way of doing that.
To enable any collection or model to synchronize from both the localStorage and a server, Backbone's sync function can be overridden:
Backbone.sync = (function(sync) {
return function(method, model, options) {
options = options || {};
var key = _.result(model, 'localStorage'),
response;
// if the localStorage property exist on the model/collection
// first try to sync with the localStorage
if (key) {
switch (method) {
case 'create':
case 'update':
var data = model.toJSON(),
text = JSON.stringify(data);
localStorage.setItem(key, text);
break;
case 'delete':
localStorage.removeItem(key);
break;
case 'read':
response = JSON.parse(localStorage.getItem(key));
if (response) model.set(response, { parse: true });
break;
}
}
// then, always sync with the server as it normally would
return sync.apply(this, arguments);
};
})(Backbone.sync);
This way, if a model or a collection as a localStorage
property, it'll first sync with the localStorage, then it'll make the original sync.
Example model and collection:
var BarModel = Backbone.Model.extend({
urlRoot: 'some/url',
localStorage: function() {
return 'bars-' + this.id;
},
});
var BarCollection = Backbone.Collection.extend({
model: BarModel,
url: '/some/url',
localStorage: 'bars',
});