Skip to content

Commit 9afdf9e

Browse files
committed
Add LocalStorage store, fix more unit tests on other browsers, fix caching
of queries
1 parent b8a0aa0 commit 9afdf9e

File tree

6 files changed

+75
-15
lines changed

6 files changed

+75
-15
lines changed

LocalDB.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
define(['./db/has!indexeddb?./db/IndexedDB:./db/SQL'],
1+
define(['./db/has!indexeddb?./db/IndexedDB:sql?./db/SQL:./db/LocalStorage'],
22
function(LocalDB){
33
// module:
44
// ./store/LocalDB

QueryResults.js

+4-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ define(['dojo/_base/lang', 'dojo/when'], function (lang, when) {
22
function forEach(callback, instance) {
33
return when(this, function(data) {
44
for (var i = 0, l = data.length; i < l; i++){
5-
callback.call(instance, data[i], data);
5+
callback.call(instance, data[i], i, data);
66
}
77
});
88
}
@@ -18,7 +18,9 @@ define(['dojo/_base/lang', 'dojo/when'], function (lang, when) {
1818
data.totalLength || data.length;
1919
// make it available on the resolved data
2020
data.totalLength = totalLength;
21-
return totalLength;
21+
// don't return the totalLength promise unless we need to, to avoid
22+
// triggering a lazy promise
23+
return !hasTotalLength && totalLength;
2224
});
2325
// make the totalLength available on the promise (whether through the options or the enventual
2426
// access to the resolved data)

Store.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -121,8 +121,8 @@ define([
121121
forEach: function (callback, thisObject) {
122122
var collection = this;
123123
return when(this.fetch(), function (data) {
124-
for (var i = 0, l = data.length; i < l; i++) {
125-
callback.call(thisObject, data[i], i, collection);
124+
for (var i = 0, item; (item = data[i]) !== undefined; i++) {
125+
callback.call(thisObject, item, i, collection);
126126
}
127127
return data;
128128
});

db/IndexedDB.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -447,12 +447,14 @@ define([
447447
var filter;
448448
var union;
449449
var filterQuery = {};
450+
var filterOperator;
450451
var sortOption;
451452
// iterate through the query log, applying each querier
452453
this.queryLog.forEach(function (entry) {
453454
var type = entry.type;
454455
var args = entry.normalizedArguments;
455456
if (type === 'filter') {
457+
filterOperator = args;
456458
var oldFilter = filter;
457459
filter = oldFilter ? function (data) {
458460
return entry.querier(oldFilter(data));
@@ -583,6 +585,7 @@ define([
583585
return {
584586
filter: union || filterQuery,
585587
filterFunction: filter,
588+
filterOperator: filterOperator || null,
586589
sort: sortOption
587590
};
588591
},
@@ -646,7 +649,7 @@ define([
646649
var value = filterQuery[key];
647650
tryIndex(key, null, value && (value.from || value.to) ? 0.1 : 1);
648651
}
649-
var queryId = JSON.stringify(filterQuery) + '-' + JSON.stringify(sortOption);
652+
var queryId = JSON.stringify(query.filterOperator) + '-' + JSON.stringify(sortOption);
650653

651654
var descending;
652655
if (sortOption) {

db/LocalStorage.js

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
define([
2+
'dojo/_base/declare',
3+
'../Memory'
4+
],
5+
function(declare, Memory) {
6+
// a very simple localStorage-based store, that basically loads everything
7+
// in memory and executes on it there. localStorage doesn't really provide
8+
// any real querying functionality, so might just as well do it all in memory
9+
return declare([Memory], {
10+
dbPrefix: 'dojo-db',
11+
storeName: 'default',
12+
constructor: function () {
13+
// load all the data from the local storage
14+
var data = [];
15+
var prefix = this.prefix = this.dbPrefix + '-' + this.storeName + '-';
16+
for (var i = 0, l = localStorage.length; i < l; i++) {
17+
var key = localStorage.key(i);
18+
if (key.slice(0, prefix.length) === prefix) {
19+
data.push(JSON.parse(localStorage.getItem(key)));
20+
}
21+
}
22+
this.setData(data);
23+
},
24+
putSync: function (object) {
25+
// addSync and all the async update methods eventually go through this
26+
var result = this.inherited(arguments);
27+
// prefix and store
28+
localStorage.setItem(this.prefix + this.getIdentity(object), JSON.stringify(object));
29+
return result;
30+
},
31+
removeSync: function (id) {
32+
localStorage.removeItem(this.prefix + id);
33+
return this.inherited(arguments);
34+
}
35+
});
36+
});

tests/LocalStorage.js

+28-9
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@ define([
22
'intern!object',
33
'intern/chai!assert',
44
'../db/has!indexeddb?../db/IndexedDB',
5-
'../db/SQL',
5+
'../db/has!sql?../db/SQL',
6+
'../db/LocalStorage',
67
'dojo/promise/all',
78
'dojo/sniff'
8-
], function (registerSuite, assert, IndexedDB, SQL, all, has) {
9+
], function (registerSuite, assert, IndexedDB, SQL, LocalStorage, all, has) {
910
var data = [
1011
{id: 1, name: 'one', prime: false, mappedTo: 'E', words: ['banana']},
1112
{id: 2, name: 'two', even: true, prime: true, mappedTo: 'D', words: ['banana', 'orange']},
@@ -39,6 +40,7 @@ define([
3940
if (window.openDatabase) {
4041
registerSuite(testsForDB('dstore/db/SQL', SQL));
4142
}
43+
registerSuite(testsForDB('dstore/db/LocalStorage', LocalStorage));
4244
function testsForDB(name, DB) {
4345
// need to reset availability
4446
dbConfig.available = null;
@@ -73,15 +75,15 @@ define([
7375
});
7476
}
7577
}
76-
var forEachResults = collection.forEach(function(object) {
78+
var forEachResults = collection.forEach(function (object) {
7779
console.log("id check", i, results[i], object.id);
7880
assert.strictEqual(results[i++], object.id);
7981
});
8082
return forEachResults.then(function () {
8183
console.log("results", results);
8284
assert.strictEqual(results.length, i);
8385
if (options && options.range) {
84-
return forEachResults.totalLength.then(function(total) {
86+
return forEachResults.totalLength.then(function (total) {
8587
assert.strictEqual(results.length, total);
8688
});
8789
}
@@ -92,10 +94,12 @@ define([
9294
name: name,
9395
setup: function () {
9496
var results = [];
95-
return db.forEach(function(object) {
96-
// clear the data
97-
results.push(db.remove(object.id));
98-
}).then(function() {
97+
return db.fetch().then(function (data) {
98+
// make a copy
99+
data = data.slice(0);
100+
for (var i = 0, l = data.length; i < l; i++) {
101+
results.push(db.remove(data[i].id));
102+
}
99103
return all(results);
100104
}).then(function() {
101105
results = [];
@@ -158,11 +162,26 @@ define([
158162
db.add({id: 6, name: 'six', prime: false, words: ['pineapple', 'orange juice']})
159163
]).then(function() {
160164
return all([
161-
testQuery(new Filter().gte('name', 's').lte('name', 'u'), [6, 3])(),
165+
testQuery(new Filter().gte('name', 's').lte('name', 'u'), {sort:[{property: 'id'}]}, [3, 6])(),
162166
testQuery(new Filter().contains('words', [new Filter().match('words', /^orange/)]), {multi: true}, [3, 6])()
163167
]);
164168
});
165169
});
170+
},
171+
'reload db': function () {
172+
// reload the DB store and make sure the data is still there
173+
dbConfig.openRequest = null;
174+
db = new DB({dbConfig: dbConfig, storeName: 'test'});
175+
return db.get(1).then(function(one) {
176+
assert.strictEqual(one.id, 1);
177+
assert.strictEqual(one.name, 'one');
178+
assert.strictEqual(one.prime, false);
179+
assert.strictEqual(one.mappedTo, 'E');
180+
return all([
181+
testQuery(new Filter().gte('name', 's').lte('name', 'u'), {sort:[{property: 'id'}]}, [3, 6])(),
182+
testQuery(new Filter().contains('words', [new Filter().match('words', /^orange/)]), {multi: true}, [3, 6])()
183+
]);
184+
});
166185
}
167186

168187
};

0 commit comments

Comments
 (0)