Skip to content

Commit

Permalink
#69 better caching of self and current collections
Browse files Browse the repository at this point in the history
  • Loading branch information
uglymunky committed Jun 17, 2014
1 parent 53bdf73 commit 9d60bb7
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 46 deletions.
51 changes: 30 additions & 21 deletions src/backbone.siren.js
Original file line number Diff line number Diff line change
Expand Up @@ -494,19 +494,26 @@ _.extend(BbSiren, {
*
* @param {Backbone.Siren.Store} store
* @param {Backbone.Siren.Collection} collection
* @param {String} [representationToStore] limit which representation of the collection we want to store.
* Can be "current" or "self".
*/
, addCollectionToStore: function (store, collection, storeCurrentOnly) {
var currentUrl = collection.link('current');
if (currentUrl) {
store.addCollection(collection, 'current');
}
, addCollectionToStore: function (store, collection, representationToStore) {
var currentUrl;

// @todo, by having objects automatically added to the store on instantiation we end up having to pass
// around store option. It feels a bit messy doing things this way. Consider re-visiting so that
// objects no longer add themselves to the store on instantiation.
if (! storeCurrentOnly) {
store.addCollection(collection, 'self');
if (representationToStore) {
store.addCollection(collection, representationToStore);
return;
}

currentUrl = collection.link('current');
if (currentUrl) {
store.addCollection(collection, 'current');
}

store.addCollection(collection, 'self');
}


Expand Down Expand Up @@ -567,31 +574,33 @@ _.extend(BbSiren, {
, parseCollection: function (rawCollection, options) {
options = options || {};

var collection, currentUrl
, createNewCollectionFlag = true
var selfCollection, currentCollection, collection, currentUrl
, store = options.store;

if (store) {
collection = store.get(rawCollection);
if (collection) {
collection.update(rawCollection, options);
createNewCollectionFlag = false;
options.storeCurrentOnly = true;
selfCollection = store.get(rawCollection);
if (selfCollection) {
selfCollection.update(rawCollection, options);
} else {
options.representationToStore = 'self';
selfCollection = new Backbone.Siren.Collection(rawCollection, options);
}

// Is it a "current" collection?
currentUrl = getRawEntityUrl(rawCollection, 'current');
if (currentUrl) {
collection = store.get(currentUrl);
if (collection) {
collection.update(rawCollection, options);
currentCollection = store.get(currentUrl);

if (currentCollection) {
currentCollection.update(rawCollection, options);
} else {
createNewCollectionFlag = true;
options.representationToStore = 'current';
currentCollection = new Backbone.Siren.Collection(rawCollection, options);
}
}
}

if (createNewCollectionFlag) {
collection = currentCollection || selfCollection;
} else {
collection = new Backbone.Siren.Collection(rawCollection, options);
}

Expand Down Expand Up @@ -1160,7 +1169,7 @@ _.extend(BbSiren, {

if (options.store) {
this.siren.store = options.store;
BbSiren.addCollectionToStore(options.store, this, !!options.storeCurrentOnly);
BbSiren.addCollectionToStore(options.store, this, options.representationToStore);
}

if (options.ajaxOptions) {
Expand Down
59 changes: 34 additions & 25 deletions test/spec/backbone.siren.js
Original file line number Diff line number Diff line change
Expand Up @@ -195,13 +195,23 @@ describe('Backbone.Siren: ', function () {
});


it('does not add the "self" collection to the store if `storeCurrentOnly` is set to `true`', function () {
it('only adds the self collection to the store if `representationToStore` is set to `self`', function () {
var currentCollection = new Backbone.Siren.Collection(rawCurrentCollection);
var store = new Backbone.Siren.Store();

Backbone.Siren.addCollectionToStore(store, currentCollection, true);
expect(store.get(currentCollection.link('self'))).not.toBeDefined();
Backbone.Siren.addCollectionToStore(store, currentCollection, 'self');
expect(store.get(currentCollection.link('self'))).toBeDefined();
expect(store.get(currentCollection.link('current'))).not.toBeDefined();
});


it('only adds the current collection to the store if `representationToStore` is set to `collection`', function () {
var currentCollection = new Backbone.Siren.Collection(rawCurrentCollection);
var store = new Backbone.Siren.Store();

Backbone.Siren.addCollectionToStore(store, currentCollection, 'current');
expect(store.get(currentCollection.link('current'))).toBeDefined();
expect(store.get(currentCollection.link('self'))).not.toBeDefined();
});
});

Expand Down Expand Up @@ -262,40 +272,39 @@ describe('Backbone.Siren: ', function () {

it('updates an existing collection if it is already cached', function () {
var store = new Backbone.Siren.Store();
var collection = new Backbone.Siren.Collection(rawCollection, {store: store});
var initialCollection = new Backbone.Siren.Collection(rawCollection, {store: store});
var initialStoredCollection = store.get(initialCollection.url());

// We tag the collection so that we know it's the same one (unlike models, collections don't have a "cid")
collection.tagged = true;

collection = Backbone.Siren.parseCollection(rawCollection, {store: store});
var updatedCollection = Backbone.Siren.parseCollection(rawCollection, {store: store});
var updatedStoredCollection = store.get(updatedCollection.url());

// Check the store
expect(store.get(getRawEntityUrl(rawCollection, 'self')).tagged).toBeTrue();
// Check what's in the store
expect(updatedStoredCollection).toBe(initialStoredCollection);

// Check the returned collection
expect(collection.tagged).toBeTrue();
expect(updatedCollection).toBe(initialCollection);
});


it('updates the "self" and "current" collections if they are both in the cache', function () {
var store = new Backbone.Siren.Store();
var collection = new Backbone.Siren.Collection(rawCurrentCollection, {store: store});
var collection2 = new Backbone.Siren.Collection(rawCurrentCollection2, {store: store});
var store, collection, initialStoredSelfCollection, updatedStoredSelfCollection
, initialStoredCurrentCollection, updatedStoredCurrentCollection;

// We tag the collection so that we know it's the same one
collection.tagged = true;
collection2.tagged = true;
store = new Backbone.Siren.Store();

// Update collection2
collection2 = Backbone.Siren.parseCollection(rawCurrentCollection2, {store: store});
// Create a current collection and a self collection
collection = new Backbone.Siren.Collection(rawCurrentCollection, {store: store});

// Check the store
expect(store.get(getRawEntityUrl(rawCurrentCollection2, 'self')).tagged).toBeTrue();
expect(store.get(getRawEntityUrl(rawCurrentCollection2, 'current')).tagged).toBeTrue();
initialStoredSelfCollection = store.get(getRawEntityUrl(rawCurrentCollection, 'self'));
initialStoredCurrentCollection = store.get(getRawEntityUrl(rawCurrentCollection, 'current'));

// Check the returned collection
expect(collection.tagged).toBeTrue();
expect(collection2.tagged).toBeTrue();
Backbone.Siren.parseCollection(rawCurrentCollection);

updatedStoredSelfCollection = store.get(getRawEntityUrl(rawCurrentCollection, 'self'));
updatedStoredCurrentCollection = store.get(getRawEntityUrl(rawCurrentCollection, 'current'));

expect(updatedStoredSelfCollection).toBe(initialStoredSelfCollection);
expect(updatedStoredCurrentCollection).toBe(initialStoredCurrentCollection);
});


Expand Down

0 comments on commit 9d60bb7

Please sign in to comment.