Skip to content

Commit c57ce9d

Browse files
committed
Initial support for DSCacheFactory integration.
1 parent 12aa34f commit c57ce9d

File tree

18 files changed

+225
-203
lines changed

18 files changed

+225
-203
lines changed

bower.json

-3
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,5 @@
3030
"angular-mocks": "~1.2.16",
3131
"angular-cache": "~3.0.0-beta.4",
3232
"observe-js": "~0.2.0"
33-
},
34-
"resolutions": {
35-
"angular": "~1.2.16"
3633
}
3734
}

dist/angular-data.js

+115-101
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,3 @@
1-
/**
2-
* @author Jason Dobry <[email protected]>
3-
* @file angular-data.js
4-
* @version 0.8.1 - Homepage <http://angular-data.codetrain.io/>
5-
* @copyright (c) 2014 Jason Dobry <https://github.com/jmdobry/>
6-
* @license MIT <https://github.com/jmdobry/angular-data/blob/master/LICENSE>
7-
*
8-
* @overview Data store for Angular.js.
9-
*/
101
require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({"QYwGEY":[function(require,module,exports){
112
(function (global){
123
// Copyright 2012 Google Inc.
@@ -588,16 +579,22 @@ var filter = require('./filter');
588579
* Create slice of source array or array-like object
589580
*/
590581
function slice(arr, start, end){
582+
var len = arr.length;
583+
591584
if (start == null) {
592585
start = 0;
593586
} else if (start < 0) {
594-
start = Math.max(arr.length + start, 0);
587+
start = Math.max(len + start, 0);
588+
} else {
589+
start = Math.min(start, len);
595590
}
596591

597592
if (end == null) {
598-
end = arr.length;
593+
end = len;
599594
} else if (end < 0) {
600-
end = Math.max(arr.length + end, 0);
595+
end = Math.max(len + end, 0);
596+
} else {
597+
end = Math.min(end, len);
601598
}
602599

603600
var result = [];
@@ -1717,14 +1714,15 @@ function destroy(resourceName, id, options) {
17171714
deferred.reject(new this.errors.RuntimeError(errorPrefix + resourceName + ' is not a registered resource!'));
17181715
} else if (!this.utils.isString(id) && !this.utils.isNumber(id)) {
17191716
deferred.reject(new this.errors.IllegalArgumentError(errorPrefix + 'id: Must be a string or a number!', { id: { actual: typeof id, expected: 'string|number' } }));
1720-
} else if (!(id in this.store[resourceName].index)) {
1721-
deferred.reject(new this.errors.RuntimeError(errorPrefix + 'id: "' + id + '" not found!'));
17221717
} else {
1723-
var definition = this.definitions[resourceName],
1724-
resource = this.store[resourceName],
1725-
_this = this;
1718+
var item = this.get(resourceName, id);
1719+
if (!item) {
1720+
deferred.reject(new this.errors.RuntimeError(errorPrefix + 'id: "' + id + '" not found!'));
1721+
} else {
1722+
var definition = this.definitions[resourceName],
1723+
resource = this.store[resourceName],
1724+
_this = this;
17261725

1727-
if (id in resource.index) {
17281726
promise = promise
17291727
.then(function (attrs) {
17301728
return _this.$q.promisify(definition.beforeDestroy)(resourceName, attrs);
@@ -1733,15 +1731,13 @@ function destroy(resourceName, id, options) {
17331731
return _this.adapters[options.adapter || definition.defaultAdapter].destroy(definition, id, options);
17341732
})
17351733
.then(function () {
1736-
return _this.$q.promisify(definition.afterDestroy)(resourceName, resource.index[id]);
1734+
return _this.$q.promisify(definition.afterDestroy)(resourceName, item);
17371735
})
17381736
.then(function () {
17391737
_this.eject(resourceName, id);
17401738
return id;
17411739
});
1742-
deferred.resolve(resource.index[id]);
1743-
} else {
1744-
deferred.resolve();
1740+
deferred.resolve(item);
17451741
}
17461742
}
17471743

@@ -1964,12 +1960,7 @@ function processResults(utils, data, resourceName, queryHash) {
19641960
resource.completedQueries[queryHash] = new Date().getTime();
19651961

19661962
// Merge the new values into the cache
1967-
for (var i = 0; i < data.length; i++) {
1968-
this.inject(resourceName, data[i]);
1969-
}
1970-
1971-
// Update the data store's index for this resource
1972-
resource.index = utils.toLookup(resource.collection, this.definitions[resourceName].idAttribute);
1963+
this.inject(resourceName, data);
19731964

19741965
// Update modified timestamp of collection
19751966
resource.collectionModified = utils.updateTimestamp(resource.collectionModified);
@@ -2252,7 +2243,7 @@ function refresh(resourceName, id, options) {
22522243
} else {
22532244
options.bypassCache = true;
22542245

2255-
if (id in this.store[resourceName].index) {
2246+
if (this.get(resourceName, id)) {
22562247
return this.find(resourceName, id, options);
22572248
} else {
22582249
return false;
@@ -2319,61 +2310,63 @@ function save(resourceName, id, options) {
23192310
deferred.reject(new this.errors.IllegalArgumentError(errorPrefix + 'id: Must be a string or a number!', { id: { actual: typeof id, expected: 'string|number' } }));
23202311
} else if (!this.utils.isObject(options)) {
23212312
deferred.reject(new this.errors.IllegalArgumentError(errorPrefix + 'options: Must be an object!', { options: { actual: typeof options, expected: 'object' } }));
2322-
} else if (!(id in this.store[resourceName].index)) {
2323-
deferred.reject(new this.errors.RuntimeError(errorPrefix + 'id: "' + id + '" not found!'));
23242313
} else {
2325-
var definition = this.definitions[resourceName],
2326-
resource = this.store[resourceName],
2327-
_this = this;
2314+
var item = this.get(resourceName, id);
2315+
if (!item) {
2316+
deferred.reject(new this.errors.RuntimeError(errorPrefix + 'id: "' + id + '" not found!'));
2317+
} else {
2318+
var definition = this.definitions[resourceName],
2319+
resource = this.store[resourceName],
2320+
_this = this;
23282321

2329-
promise = promise
2330-
.then(function (attrs) {
2331-
return _this.$q.promisify(definition.beforeValidate)(resourceName, attrs);
2332-
})
2333-
.then(function (attrs) {
2334-
return _this.$q.promisify(definition.validate)(resourceName, attrs);
2335-
})
2336-
.then(function (attrs) {
2337-
return _this.$q.promisify(definition.afterValidate)(resourceName, attrs);
2338-
})
2339-
.then(function (attrs) {
2340-
return _this.$q.promisify(definition.beforeUpdate)(resourceName, attrs);
2341-
})
2342-
.then(function (attrs) {
2343-
if (options.changesOnly) {
2344-
resource.observers[id].deliver();
2345-
var toKeep = [],
2346-
changes = _this.changes(resourceName, id);
2347-
2348-
for (var key in changes.added) {
2349-
toKeep.push(key);
2350-
}
2351-
for (key in changes.changed) {
2352-
toKeep.push(key);
2353-
}
2354-
changes = _this.utils.pick(attrs, toKeep);
2355-
if (_this.utils.isEmpty(changes)) {
2356-
// no changes, return
2357-
return attrs;
2358-
} else {
2359-
attrs = changes;
2322+
promise = promise
2323+
.then(function (attrs) {
2324+
return _this.$q.promisify(definition.beforeValidate)(resourceName, attrs);
2325+
})
2326+
.then(function (attrs) {
2327+
return _this.$q.promisify(definition.validate)(resourceName, attrs);
2328+
})
2329+
.then(function (attrs) {
2330+
return _this.$q.promisify(definition.afterValidate)(resourceName, attrs);
2331+
})
2332+
.then(function (attrs) {
2333+
return _this.$q.promisify(definition.beforeUpdate)(resourceName, attrs);
2334+
})
2335+
.then(function (attrs) {
2336+
if (options.changesOnly) {
2337+
resource.observers[id].deliver();
2338+
var toKeep = [],
2339+
changes = _this.changes(resourceName, id);
2340+
2341+
for (var key in changes.added) {
2342+
toKeep.push(key);
2343+
}
2344+
for (key in changes.changed) {
2345+
toKeep.push(key);
2346+
}
2347+
changes = _this.utils.pick(attrs, toKeep);
2348+
if (_this.utils.isEmpty(changes)) {
2349+
// no changes, return
2350+
return attrs;
2351+
} else {
2352+
attrs = changes;
2353+
}
23602354
}
2361-
}
2362-
return _this.adapters[options.adapter || definition.defaultAdapter].update(definition, id, attrs, options);
2363-
})
2364-
.then(function (data) {
2365-
return _this.$q.promisify(definition.afterUpdate)(resourceName, data);
2366-
})
2367-
.then(function (data) {
2368-
_this.inject(definition.name, data, options);
2369-
resource.previousAttributes[id] = _this.utils.deepMixIn({}, data);
2370-
resource.saved[id] = _this.utils.updateTimestamp(resource.saved[id]);
2371-
return _this.get(resourceName, id);
2372-
});
2355+
return _this.adapters[options.adapter || definition.defaultAdapter].update(definition, id, attrs, options);
2356+
})
2357+
.then(function (data) {
2358+
return _this.$q.promisify(definition.afterUpdate)(resourceName, data);
2359+
})
2360+
.then(function (data) {
2361+
_this.inject(definition.name, data, options);
2362+
resource.previousAttributes[id] = _this.utils.deepMixIn({}, data);
2363+
resource.saved[id] = _this.utils.updateTimestamp(resource.saved[id]);
2364+
return _this.get(resourceName, id);
2365+
});
23732366

2374-
deferred.resolve(resource.index[id]);
2367+
deferred.resolve(item);
2368+
}
23752369
}
2376-
23772370
return promise;
23782371
}
23792372

@@ -2468,11 +2461,21 @@ function DSProvider() {
24682461
var defaults = this.defaults = new BaseConfig();
24692462

24702463
this.$get = [
2471-
'$rootScope', '$log', '$q', 'DSHttpAdapter', 'DSUtils', 'DSErrors',
2472-
function ($rootScope, $log, $q, DSHttpAdapter, DSUtils, DSErrors) {
2464+
'$rootScope', '$log', '$q', 'DSHttpAdapter', 'DSUtils', 'DSErrors', 'DSCacheFactory',
2465+
function ($rootScope, $log, $q, DSHttpAdapter, DSUtils, DSErrors, DSCacheFactory) {
24732466

24742467
var syncMethods = require('./sync_methods'),
2475-
asyncMethods = require('./async_methods');
2468+
asyncMethods = require('./async_methods'),
2469+
cache;
2470+
2471+
try {
2472+
cache = angular.injector(['angular-data.DSCacheFactory']).get('DSCacheFactory');
2473+
} catch (err) {
2474+
$log.warn(err);
2475+
$log.warn('DSCacheFactory is unavailable. Resorting to the lesser capabilities of $cacheFactory.');
2476+
cache = angular.injector(['ng']).get('$cacheFactory');
2477+
}
2478+
24762479

24772480
/**
24782481
* @doc interface
@@ -2488,6 +2491,8 @@ function DSProvider() {
24882491
$log: $log,
24892492
$q: $q,
24902493

2494+
cacheFactory: cache,
2495+
24912496
/**
24922497
* @doc property
24932498
* @id DS.properties:defaults
@@ -2615,12 +2620,11 @@ function changes(resourceName, id) {
26152620
throw new this.errors.IllegalArgumentError(errorPrefix + 'id: Must be a string or a number!', { id: { actual: typeof id, expected: 'string|number' } });
26162621
}
26172622

2618-
var resource = this.store[resourceName];
2619-
26202623
try {
2621-
if (resource.index[id]) {
2622-
resource.observers[id].deliver();
2623-
return this.utils.diffObjectFromOldObject(resource.index[id], resource.previousAttributes[id]);
2624+
var item = this.get(resourceName, id);
2625+
if (item) {
2626+
this.store[resourceName].observers[id].deliver();
2627+
return this.utils.diffObjectFromOldObject(item, this.store[resourceName].previousAttributes[id]);
26242628
}
26252629
} catch (err) {
26262630
throw new this.errors.UnhandledError(err);
@@ -2714,11 +2718,12 @@ function defineResource(definition) {
27142718
Resource.prototype = this.defaults;
27152719
this.definitions[definition.name] = new Resource(this.utils, definition);
27162720

2721+
var cache = this.cacheFactory('DS.' + definition.name);
27172722
this.store[definition.name] = {
27182723
collection: [],
27192724
completedQueries: {},
27202725
pendingQueries: {},
2721-
index: {},
2726+
index: cache,
27222727
modified: {},
27232728
saved: {},
27242729
previousAttributes: {},
@@ -2791,7 +2796,8 @@ function _eject(definition, resource, id) {
27912796
resource.collection.splice(i, 1);
27922797
resource.observers[id].close();
27932798
delete resource.observers[id];
2794-
delete resource.index[id];
2799+
2800+
resource.index.remove(id);
27952801
delete resource.previousAttributes[id];
27962802
delete resource.modified[id];
27972803
delete resource.saved[id];
@@ -3166,14 +3172,15 @@ function get(resourceName, id, options) {
31663172

31673173
try {
31683174
// cache miss, request resource from server
3169-
if (!(id in this.store[resourceName].index) && options.loadFromServer) {
3175+
var item = this.store[resourceName].index.get(id);
3176+
if (!item && options.loadFromServer) {
31703177
this.find(resourceName, id).then(null, function (err) {
31713178
throw err;
31723179
});
31733180
}
31743181

31753182
// return resource from cache
3176-
return this.store[resourceName].index[id];
3183+
return item;
31773184
} catch (err) {
31783185
throw new this.errors.UnhandledError(err);
31793186
}
@@ -3232,7 +3239,7 @@ function hasChanges(resourceName, id) {
32323239

32333240
try {
32343241
// return resource from cache
3235-
if (id in this.store[resourceName].index) {
3242+
if (this.get(resourceName, id)) {
32363243
return diffIsEmpty(this.utils, this.changes(resourceName, id));
32373244
} else {
32383245
return false;
@@ -3399,24 +3406,31 @@ function _inject(definition, resource, attrs) {
33993406
if (!(definition.idAttribute in attrs)) {
34003407
throw new _this.errors.RuntimeError(errorPrefix + 'attrs: Must contain the property specified by `idAttribute`!');
34013408
} else {
3402-
var id = attrs[definition.idAttribute];
3409+
var id = attrs[definition.idAttribute],
3410+
item = this.get(definition.name, id);
34033411

3404-
if (!(id in resource.index)) {
3405-
resource.index[id] = {};
3412+
if (!item) {
3413+
item = {};
34063414
resource.previousAttributes[id] = {};
34073415

3408-
_this.utils.deepMixIn(resource.index[id], attrs);
3416+
_this.utils.deepMixIn(item, attrs);
34093417
_this.utils.deepMixIn(resource.previousAttributes[id], attrs);
34103418

3411-
resource.collection.push(resource.index[id]);
3419+
resource.collection.push(item);
34123420

3413-
resource.observers[id] = new observe.ObjectObserver(resource.index[id], _react);
3421+
resource.observers[id] = new observe.ObjectObserver(item, _react);
3422+
resource.index.put(id, item);
34143423

34153424
_react({}, {}, {}, function () {
34163425
return id;
34173426
});
34183427
} else {
3419-
_this.utils.deepMixIn(resource.index[id], attrs);
3428+
_this.utils.deepMixIn(item, attrs);
3429+
if (typeof resource.index.touch === 'function') {
3430+
resource.index.touch(id);
3431+
} else {
3432+
resource.index.put(id, resource.index.get(id));
3433+
}
34203434
resource.observers[id].deliver();
34213435
}
34223436
resource.saved[id] = _this.utils.updateTimestamp(resource.saved[id]);
@@ -3896,7 +3910,7 @@ module.exports = [function () {
38963910
* [DSUtils](/documentation/api/api/DSUtils) has some useful utility methods.
38973911
* [DSErrors](/documentation/api/api/DSErrors) provides references to the various errors thrown by the data store.
38983912
*/
3899-
angular.module('angular-data.DS', ['ng'])
3913+
angular.module('angular-data.DS', ['ng', 'angular-data.DSCacheFactory'])
39003914
.service('DSUtils', require('./utils'))
39013915
.service('DSErrors', require('./errors'))
39023916
.provider('DSHttpAdapter', require('./adapters/http'))
@@ -4016,4 +4030,4 @@ module.exports = [function () {
40164030
};
40174031
}];
40184032

4019-
},{"mout/array/contains":3,"mout/array/filter":4,"mout/array/slice":7,"mout/array/sort":8,"mout/array/toLookup":9,"mout/lang/isEmpty":14,"mout/object/deepMixIn":21,"mout/object/forOwn":23,"mout/object/pick":25,"mout/string/makePath":26,"mout/string/upperCase":27}]},{},[53])
4033+
},{"mout/array/contains":3,"mout/array/filter":4,"mout/array/slice":7,"mout/array/sort":8,"mout/array/toLookup":9,"mout/lang/isEmpty":14,"mout/object/deepMixIn":21,"mout/object/forOwn":23,"mout/object/pick":25,"mout/string/makePath":26,"mout/string/upperCase":27}]},{},[53])

dist/angular-data.min.js

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

karma.conf.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ module.exports = function (config) {
2121
files: [
2222
'bower_components/angular/angular.js',
2323
'bower_components/angular-mocks/angular-mocks.js',
24+
'bower_components/angular-cache/dist/angular-cache.js',
2425
'dist/angular-data.js',
2526
'test/integration/**/*.js',
26-
// 'test/integration/datastore/async_methods/save/*.js',
2727
'karma.start.js'
2828
],
2929

0 commit comments

Comments
 (0)