Skip to content

Commit

Permalink
Merge pull request #383 from crwang/master
Browse files Browse the repository at this point in the history
Added in clear methods to model and collection stores
  • Loading branch information
saponifi3d committed Dec 10, 2014
2 parents ceffdb2 + ca42ebd commit 2dc4dd2
Show file tree
Hide file tree
Showing 4 changed files with 259 additions and 39 deletions.
29 changes: 29 additions & 0 deletions shared/store/collection_store.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,38 @@ _.extend(CollectionStore.prototype, Super.prototype, {
return cachedCollection;
},

clear: function(collectionName, params) {
if (!_.isUndefined(collectionName) && params) {
var key = this._getStoreKey(collectionName, params);
return Super.prototype.clear.call(this, key);
} else if (!_.isUndefined(collectionName) && !params) {
var cachedItems = this._getCachedItemsByCollection(collectionName),
self = this,
storeKey;
_.each(cachedItems, function (item) {
storeKey = self._getStoreKey(collectionName, item.value.params);
Super.prototype.clear.call(self, storeKey);
});
} else {
return Super.prototype.clear.call(this, null);
}
},

mergeParams: function(collectionName, params, callback) {
this.modelUtils.getCollectionConstructor(collectionName, function(Collection) {
var mergedParams = _.extend({}, Collection.prototype.defaultParams, params);
callback(mergedParams);
});
},

_getCachedItemsByCollection:function(collectionName) {
var prefix = this._formatKey(this.modelUtils.underscorize(collectionName));

return _.filter(this.cache, function(val, key) {
return startsWith(key, prefix);
});
},

_getStoreKeyForCollection: function(collection, params) {
var collectionName = this.modelUtils.modelName(collection.constructor);

Expand All @@ -57,3 +82,7 @@ function sortParams(params) {
});
return sorted;
}

function startsWith(string, prefix) {
return string.slice(0, prefix.length) == prefix;
}
24 changes: 24 additions & 0 deletions shared/store/model_store.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,23 @@ _.extend(ModelStore.prototype, Super.prototype, {
return Super.prototype.get.call(this, key);
},

clear: function(modelName, id) {
if (modelName && id) {
var key = this._getModelStoreKey(modelName, id);
return Super.prototype.clear.call(this, key);
} else if (modelName && !id) {
var cachedItems = this._getCachedItemsByModel(modelName),
self = this,
modelStoreKey;
_.each(cachedItems, function (item) {
modelStoreKey = self._getModelStoreKey(modelName, item.value.id);
Super.prototype.clear.call(self, modelStoreKey);
});
} else {
return Super.prototype.clear.call(this, null);
}
},

find: function(modelName, params) {
var prefix = this._formatKey(this._keyPrefix(modelName)),
keys = Object.keys(this.cache),
Expand All @@ -52,6 +69,13 @@ _.extend(ModelStore.prototype, Super.prototype, {
}
},

_getCachedItemsByModel:function(modelName) {
var prefix = this._formatKey(this._keyPrefix(modelName));
return _.filter(this.cache, function(val, key) {
return startsWith(key, prefix);
});
},

_formatKey: function(key) {
return Super.prototype._formatKey.call(this, "_ms:" + key);
},
Expand Down
90 changes: 90 additions & 0 deletions test/shared/store/collection_store.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -149,4 +149,94 @@ describe('CollectionStore', function() {
should.exist(results);
results.should.be.equal(collection);
});

context("there is data to be cleared", function() {
var collection, collection2, anotherCollection, models, models2, modelsAnother,
params, params2, resultsCollection;

beforeEach(function() {
models = [
{
foo: 'bar',
id: 1
}, {
foo: 'bot',
id: 2
}
];
models2 = [
{
foo: 'bar',
id: 11
}, {
foo: 'bot',
id: 12
}
];
modelsAnother = [
{
foo: 'bee',
id: 111
}, {
foo: 'hum',
id: 112
}
];
params = {
offset: 0
};
params2 = {offset: 10};
collection = new BaseCollection(models, {params: params});
collection2 = new BaseCollection(models2, {params: params2});

function AnotherCollection() {
AnotherCollection.super_.apply(this, arguments);
}
util.inherits(AnotherCollection, BaseCollection);

anotherCollection = new AnotherCollection(modelsAnother, {params: params });
});

it("should allow clearing out of the store by params", function() {
this.store.set(collection, params);
this.store.set(collection2, params2);
this.store.clear(collection.constructor.name, params);
resultsCollection = this.store.get(collection.constructor.name, params);
should.not.exist(resultsCollection);
resultsCollection = this.store.get(collection2.constructor.name, params2);
should.exist(resultsCollection);
});

it("should allow clearing a collection out of the store", function() {
this.store.set(collection, params);
this.store.set(collection2, params2);
this.store.set(anotherCollection, params);

resultsCollection = this.store.get(collection.constructor.name, params);
should.exist(resultsCollection);
resultsCollection = this.store.get(collection2.constructor.name, params2);
should.exist(resultsCollection);

this.store.clear(collection.constructor.name);
resultsCollection = this.store.get(collection.constructor.name, params);
should.not.exist(resultsCollection);
resultsCollection = this.store.get(collection2.constructor.name, params2);
should.not.exist(resultsCollection);
this.store.cache.should.not.be.empty;
});


it("should allow clearing out the store", function() {
this.store.set(collection, params);
this.store.set(collection2, params2);
this.store.set(anotherCollection, params);

this.store.clear();
resultsCollection = this.store.get(collection.constructor.name, params);
should.not.exist(resultsCollection);
resultsCollection = this.store.get(collection2.constructor.name, params2);
should.not.exist(resultsCollection);
this.store.cache.should.be.empty;
});
});
});
155 changes: 116 additions & 39 deletions test/shared/store/model_store.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,17 @@ function MyModel() {
}
util.inherits(MyModel, BaseModel);

function MyModel2() {
MyModel2.super_.apply(this, arguments);
}
util.inherits(MyModel2, BaseModel);

function App() {}

addClassMapping.add(modelUtils.modelName(MyModel), MyModel);

describe('ModelStore', function() {
var model, result;
beforeEach(function() {
this.app = new App({modelUtils: modelUtils});
this.store = new ModelStore({
Expand Down Expand Up @@ -47,7 +53,7 @@ describe('ModelStore', function() {
});

it("should support custom idAttribute", function() {
var model, modelAttrs, result;
var modelAttrs;

modelAttrs = {
foo: 'bar',
Expand All @@ -67,52 +73,123 @@ describe('ModelStore', function() {
result.should.eql(model);
});

it("should support returning a model instance", function() {
var model, modelAttrs, resultModel;
context("there is a model with id", function () {
var defaultModelAttrs;

modelAttrs = {
foo: 'bar',
id: 1
};
model = new MyModel(modelAttrs, {app: this.app});
this.store.set(model);
resultModel = this.store.get('my_model', 1, true);
resultModel.should.be.an.instanceOf(BaseModel);
resultModel.toJSON().should.eql(modelAttrs);
resultModel.app.should.eql(this.app);
resultModel.should.be.equal(model);
});
beforeEach(function() {
defaultModelAttrs = {
foo: 'bar',
id: 1
};

describe('find', function(){
function MySecondModel() {
MySecondModel.super_.apply(this, arguments);
}
util.inherits(MySecondModel, BaseModel);
model = new MyModel(defaultModelAttrs, { app: this.app });
});

addClassMapping.add(modelUtils.modelName(MySecondModel), MySecondModel);
it("should get and set the values for a model", function() {
var resultModel;

it('should find a model on custom attributes', function(){
var model, modelAttrs, result;
modelAttrs = {
foo: 'bar',
id: 1
};
model = new MyModel(modelAttrs);
this.store.set(model);
result = this.store.find('my_model', {foo: 'bar'});
result.should.eql(model);
resultModel = this.store.get('my_model', defaultModelAttrs.id);
resultModel.should.eql(model);
});

it('should skip different models, even when they match the query', function(){
var model, modelAttrs, result;
modelAttrs = {
foo: 'bar',
id: 1
};
model = new MySecondModel(modelAttrs);
it("should support returning a model instance", function() {
var resultModel;

this.store.set(model);
result = this.store.find('my_model', {foo: 'bar'});
should.equal(result, undefined);
resultModel = this.store.get('my_model', defaultModelAttrs.id, true);
resultModel.should.be.an.instanceOf(BaseModel);
resultModel.toJSON().should.eql(defaultModelAttrs);
resultModel.app.should.eql(this.app);
resultModel.should.be.equal(model);
});

it("should be able to be cleared from the store by id", function() {
var resultModel;

this.store.set(model);
resultModel = this.store.get('my_model', defaultModelAttrs.id, true);
should.exist(resultModel);
this.store.clear('my_model', defaultModelAttrs.id);
resultModel = this.store.get('my_model', defaultModelAttrs.id, true);
should.not.exist(resultModel);
});

describe('find', function(){
function MySecondModel() {
MySecondModel.super_.apply(this, arguments);
}
util.inherits(MySecondModel, BaseModel);

addClassMapping.add(modelUtils.modelName(MySecondModel), MySecondModel);

it('should find a model on custom attributes', function(){
this.store.set(model);
resultModel = this.store.find('my_model', {foo: 'bar'});
resultModel.should.eql(model);
});

it('should skip different models, even when they match the query', function(){
model = new MySecondModel(defaultModelAttrs);
this.store.set(model);
resultModel = this.store.find('my_model', {foo: 'bar'});
should.equal(resultModel, undefined);
});
});
context("more than one model", function () {
var defaultModelAttrs2, model2;

beforeEach(function() {
defaultModelAttrs2 = {
foo: 'bar2',
id: 2
};
model2 = new MyModel(defaultModelAttrs2, { app: this.app });
});

it("all should be able to be cleared from the store", function() {

this.store.set(model);
this.store.set(model2);

resultModel = this.store.get('my_model', defaultModelAttrs.id, true);
should.exist(resultModel);
resultModel = this.store.get('my_model', defaultModelAttrs2.id, true);
should.exist(resultModel);
this.store.clear();
resultModel = this.store.get('my_model', defaultModelAttrs.id, true);
should.not.exist(resultModel);
resultModel = this.store.get('my_model', defaultModelAttrs2.id, true);
should.not.exist(resultModel);
});
});
context("more than one type of model", function () {
var defaultModelAttrs2, model2;

beforeEach(function() {
defaultModelAttrs2 = {
foo: 'bar2',
id: 2
};
model2 = new MyModel2(defaultModelAttrs2, { app: this.app });
});

it("should be able to be clear one full model from the store", function() {

this.store.set(model);
this.store.set(model2);

resultModel = this.store.get('my_model', defaultModelAttrs.id, true);
should.exist(resultModel);
resultModel = this.store.get('my_model2', defaultModelAttrs2.id, true);
should.exist(resultModel);

this.store.clear('my_model');
resultModel = this.store.get('my_model', defaultModelAttrs.id, true);
should.not.exist(resultModel);
resultModel = this.store.get('my_model2', defaultModelAttrs2.id, true);
should.exist(resultModel);
});
});
});
});

0 comments on commit 2dc4dd2

Please sign in to comment.