Skip to content

Commit 63e54ec

Browse files
committed
Closes #83.
1 parent 0d8a9b1 commit 63e54ec

File tree

7 files changed

+405
-27
lines changed

7 files changed

+405
-27
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
- #17 - Where predicates should be able to handle OR, not just AND
99
- #78 - Added optional callback to `bindOne` and `bindAll`
1010
- #79 - `ejectAll` should clear matching completed queries
11+
- #83 - Implement `DS.loadRelations(resourceName, instance(Id), relations[, options])`
1112

1213
##### 0.9.1 - 30 May 2014
1314

dist/angular-data.js

Lines changed: 149 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2403,6 +2403,16 @@ module.exports = {
24032403
*/
24042404
findAll: require('./findAll'),
24052405

2406+
/**
2407+
* @doc method
2408+
* @id DS.async_methods:loadRelations
2409+
* @name loadRelations
2410+
* @methodOf DS
2411+
* @description
2412+
* See [DS.loadRelations](/documentation/api/api/DS.async_methods:loadRelations).
2413+
*/
2414+
loadRelations: require('./loadRelations'),
2415+
24062416
/**
24072417
* @doc method
24082418
* @id DS.async_methods:refresh
@@ -2444,7 +2454,122 @@ module.exports = {
24442454
updateAll: require('./updateAll')
24452455
};
24462456

2447-
},{"./create":32,"./destroy":33,"./destroyAll":34,"./find":35,"./findAll":36,"./refresh":38,"./save":39,"./update":40,"./updateAll":41}],38:[function(require,module,exports){
2457+
},{"./create":32,"./destroy":33,"./destroyAll":34,"./find":35,"./findAll":36,"./loadRelations":38,"./refresh":39,"./save":40,"./update":41,"./updateAll":42}],38:[function(require,module,exports){
2458+
var errorPrefix = 'DS.loadRelations(resourceName, instance(Id), relations[, options]): ';
2459+
2460+
/**
2461+
* @doc method
2462+
* @id DS.async_methods:loadRelations
2463+
* @name loadRelations
2464+
* @description
2465+
* Asynchronously load the indicates relations of the given instance.
2466+
*
2467+
* ## Signature:
2468+
* ```js
2469+
* DS.loadRelations(resourceName, instance(Id), relations[, options])
2470+
* ```
2471+
*
2472+
* ## Example:
2473+
*
2474+
* ```js
2475+
* ```
2476+
*
2477+
* @param {string} resourceName The resource type, e.g. 'user', 'comment', etc.
2478+
* @param {string|number|object} instance The instance or the id of the instance for which relations are to be loaded.
2479+
* @param {string|array=} relations The relation(s) to load.
2480+
* @param {object=} options Optional configuration that is passed to the `find` and `findAll` methods that may be called.
2481+
*
2482+
* @returns {Promise} Promise produced by the `$q` service.
2483+
*
2484+
* ## Resolves with:
2485+
*
2486+
* - `{object}` - `item` - The instance with its loaded relations.
2487+
*
2488+
* ## Rejects with:
2489+
*
2490+
* - `{IllegalArgumentError}`
2491+
* - `{NonexistentResourceError}`
2492+
*/
2493+
function loadRelations(resourceName, instance, relations, options) {
2494+
var deferred = this.$q.defer();
2495+
var promise = deferred.promise;
2496+
var IA = this.errors.IA;
2497+
2498+
options = options || {};
2499+
2500+
if (angular.isString(instance) || angular.isNumber(instance)) {
2501+
instance = this.get(resourceName, instance);
2502+
}
2503+
2504+
if (angular.isString(relations)) {
2505+
relations = [relations];
2506+
}
2507+
2508+
try {
2509+
if (!this.definitions[resourceName]) {
2510+
throw new this.errors.NER(errorPrefix + resourceName);
2511+
} else if (!this.utils.isObject(instance)) {
2512+
throw new IA(errorPrefix + 'instance(Id): Must be a string, number or object!');
2513+
} else if (!this.utils.isArray(relations)) {
2514+
throw new IA(errorPrefix + 'relations: Must be a string or an array!');
2515+
} else if (!this.utils.isObject(options)) {
2516+
throw new IA(errorPrefix + 'options: Must be an object!');
2517+
}
2518+
2519+
var definition = this.definitions[resourceName];
2520+
var _this = this;
2521+
var tasks = [];
2522+
var fields = [];
2523+
2524+
_this.utils.forOwn(definition.relations, function (relation, type) {
2525+
_this.utils.forOwn(relation, function (def, relationName) {
2526+
if (_this.utils.contains(relations, relationName)) {
2527+
var task;
2528+
var params = {};
2529+
params[def.foreignKey] = instance[definition.idAttribute];
2530+
2531+
if (type === 'hasMany') {
2532+
task = _this.findAll(relationName, params, options);
2533+
} else if (type === 'hasOne') {
2534+
if (def.localKey && instance[def.localKey]) {
2535+
task = _this.find(relationName, instance[def.localKey], options);
2536+
} else if (def.foreignKey) {
2537+
task = _this.findAll(relationName, params, options);
2538+
}
2539+
} else {
2540+
task = _this.find(relationName, instance[def.localKey], options);
2541+
}
2542+
2543+
if (task) {
2544+
tasks.push(task);
2545+
fields.push(def.localField);
2546+
}
2547+
}
2548+
});
2549+
});
2550+
2551+
promise = promise
2552+
.then(function () {
2553+
return _this.$q.all(tasks);
2554+
})
2555+
.then(function (loadedRelations) {
2556+
angular.forEach(fields, function (field, index) {
2557+
instance[field] = loadedRelations[index];
2558+
});
2559+
return instance;
2560+
});
2561+
2562+
deferred.resolve();
2563+
} catch (err) {
2564+
deferred.reject(err);
2565+
}
2566+
2567+
return promise;
2568+
}
2569+
2570+
module.exports = loadRelations;
2571+
2572+
},{}],39:[function(require,module,exports){
24482573
var errorPrefix = 'DS.refresh(resourceName, id[, options]): ';
24492574

24502575
/**
@@ -2517,7 +2642,7 @@ function refresh(resourceName, id, options) {
25172642

25182643
module.exports = refresh;
25192644

2520-
},{}],39:[function(require,module,exports){
2645+
},{}],40:[function(require,module,exports){
25212646
var errorPrefix = 'DS.save(resourceName, id[, options]): ';
25222647

25232648
/**
@@ -2636,7 +2761,7 @@ function save(resourceName, id, options) {
26362761

26372762
module.exports = save;
26382763

2639-
},{}],40:[function(require,module,exports){
2764+
},{}],41:[function(require,module,exports){
26402765
var errorPrefix = 'DS.update(resourceName, id, attrs[, options]): ';
26412766

26422767
/**
@@ -2746,7 +2871,7 @@ function update(resourceName, id, attrs, options) {
27462871

27472872
module.exports = update;
27482873

2749-
},{}],41:[function(require,module,exports){
2874+
},{}],42:[function(require,module,exports){
27502875
var errorPrefix = 'DS.updateAll(resourceName, attrs, params[, options]): ';
27512876

27522877
/**
@@ -2865,7 +2990,7 @@ function updateAll(resourceName, attrs, params, options) {
28652990

28662991
module.exports = updateAll;
28672992

2868-
},{}],42:[function(require,module,exports){
2993+
},{}],43:[function(require,module,exports){
28692994
var utils = require('../utils')[0]();
28702995

28712996
function lifecycleNoop(resourceName, attrs, cb) {
@@ -3590,7 +3715,7 @@ function DSProvider() {
35903715

35913716
module.exports = DSProvider;
35923717

3593-
},{"../utils":60,"./async_methods":37,"./sync_methods":53}],43:[function(require,module,exports){
3718+
},{"../utils":61,"./async_methods":37,"./sync_methods":54}],44:[function(require,module,exports){
35943719
var errorPrefix = 'DS.bindAll(scope, expr, resourceName, params[, cb]): ';
35953720

35963721
/**
@@ -3670,7 +3795,7 @@ function bindOne(scope, expr, resourceName, params, cb) {
36703795

36713796
module.exports = bindOne;
36723797

3673-
},{}],44:[function(require,module,exports){
3798+
},{}],45:[function(require,module,exports){
36743799
var errorPrefix = 'DS.bindOne(scope, expr, resourceName, id[, cb]): ';
36753800

36763801
/**
@@ -3738,7 +3863,7 @@ function bindOne(scope, expr, resourceName, id, cb) {
37383863

37393864
module.exports = bindOne;
37403865

3741-
},{}],45:[function(require,module,exports){
3866+
},{}],46:[function(require,module,exports){
37423867
var errorPrefix = 'DS.changes(resourceName, id): ';
37433868

37443869
/**
@@ -3790,7 +3915,7 @@ function changes(resourceName, id) {
37903915

37913916
module.exports = changes;
37923917

3793-
},{}],46:[function(require,module,exports){
3918+
},{}],47:[function(require,module,exports){
37943919
/*jshint evil:true*/
37953920
var errorPrefix = 'DS.defineResource(definition): ';
37963921

@@ -3931,7 +4056,7 @@ function defineResource(definition) {
39314056

39324057
module.exports = defineResource;
39334058

3934-
},{}],47:[function(require,module,exports){
4059+
},{}],48:[function(require,module,exports){
39354060
var observe = require('../../../lib/observe-js/observe-js');
39364061

39374062
/**
@@ -3966,7 +4091,7 @@ function digest() {
39664091

39674092
module.exports = digest;
39684093

3969-
},{"../../../lib/observe-js/observe-js":1}],48:[function(require,module,exports){
4094+
},{"../../../lib/observe-js/observe-js":1}],49:[function(require,module,exports){
39704095
var errorPrefix = 'DS.eject(resourceName, id): ';
39714096

39724097
function _eject(definition, resource, id) {
@@ -4044,7 +4169,7 @@ function eject(resourceName, id) {
40444169

40454170
module.exports = eject;
40464171

4047-
},{}],49:[function(require,module,exports){
4172+
},{}],50:[function(require,module,exports){
40484173
var errorPrefix = 'DS.ejectAll(resourceName[, params]): ';
40494174

40504175
function _ejectAll(definition, resource, params) {
@@ -4152,7 +4277,7 @@ function ejectAll(resourceName, params) {
41524277

41534278
module.exports = ejectAll;
41544279

4155-
},{}],50:[function(require,module,exports){
4280+
},{}],51:[function(require,module,exports){
41564281
var errorPrefix = 'DS.filter(resourceName[, params][, options]): ';
41574282

41584283
/**
@@ -4231,7 +4356,7 @@ function filter(resourceName, params, options) {
42314356

42324357
module.exports = filter;
42334358

4234-
},{}],51:[function(require,module,exports){
4359+
},{}],52:[function(require,module,exports){
42354360
var errorPrefix = 'DS.get(resourceName, id[, options]): ';
42364361

42374362
/**
@@ -4290,7 +4415,7 @@ function get(resourceName, id, options) {
42904415

42914416
module.exports = get;
42924417

4293-
},{}],52:[function(require,module,exports){
4418+
},{}],53:[function(require,module,exports){
42944419
var errorPrefix = 'DS.hasChanges(resourceName, id): ';
42954420

42964421
function diffIsEmpty(utils, diff) {
@@ -4348,7 +4473,7 @@ function hasChanges(resourceName, id) {
43484473

43494474
module.exports = hasChanges;
43504475

4351-
},{}],53:[function(require,module,exports){
4476+
},{}],54:[function(require,module,exports){
43524477
module.exports = {
43534478
/**
43544479
* @doc method
@@ -4491,7 +4616,7 @@ module.exports = {
44914616
hasChanges: require('./hasChanges')
44924617
};
44934618

4494-
},{"./bindAll":43,"./bindOne":44,"./changes":45,"./defineResource":46,"./digest":47,"./eject":48,"./ejectAll":49,"./filter":50,"./get":51,"./hasChanges":52,"./inject":54,"./lastModified":55,"./lastSaved":56,"./previous":57}],54:[function(require,module,exports){
4619+
},{"./bindAll":44,"./bindOne":45,"./changes":46,"./defineResource":47,"./digest":48,"./eject":49,"./ejectAll":50,"./filter":51,"./get":52,"./hasChanges":53,"./inject":55,"./lastModified":56,"./lastSaved":57,"./previous":58}],55:[function(require,module,exports){
44954620
var observe = require('../../../lib/observe-js/observe-js');
44964621
var errorPrefix = 'DS.inject(resourceName, attrs[, options]): ';
44974622

@@ -4663,7 +4788,7 @@ function inject(resourceName, attrs, options) {
46634788

46644789
module.exports = inject;
46654790

4666-
},{"../../../lib/observe-js/observe-js":1}],55:[function(require,module,exports){
4791+
},{"../../../lib/observe-js/observe-js":1}],56:[function(require,module,exports){
46674792
var errorPrefix = 'DS.lastModified(resourceName[, id]): ';
46684793

46694794
/**
@@ -4716,7 +4841,7 @@ function lastModified(resourceName, id) {
47164841

47174842
module.exports = lastModified;
47184843

4719-
},{}],56:[function(require,module,exports){
4844+
},{}],57:[function(require,module,exports){
47204845
var errorPrefix = 'DS.lastSaved(resourceName[, id]): ';
47214846

47224847
/**
@@ -4772,7 +4897,7 @@ function lastSaved(resourceName, id) {
47724897

47734898
module.exports = lastSaved;
47744899

4775-
},{}],57:[function(require,module,exports){
4900+
},{}],58:[function(require,module,exports){
47764901
var errorPrefix = 'DS.previous(resourceName, id): ';
47774902

47784903
/**
@@ -4822,7 +4947,7 @@ function previous(resourceName, id) {
48224947

48234948
module.exports = previous;
48244949

4825-
},{}],58:[function(require,module,exports){
4950+
},{}],59:[function(require,module,exports){
48264951
/**
48274952
* @doc function
48284953
* @id errors.types:IllegalArgumentError
@@ -4955,7 +5080,7 @@ module.exports = [function () {
49555080
};
49565081
}];
49575082

4958-
},{}],59:[function(require,module,exports){
5083+
},{}],60:[function(require,module,exports){
49595084
(function (window, angular, undefined) {
49605085
'use strict';
49615086

@@ -5038,7 +5163,7 @@ module.exports = [function () {
50385163

50395164
})(window, window.angular);
50405165

5041-
},{"./adapters/http":30,"./adapters/localStorage":31,"./datastore":42,"./errors":58,"./utils":60}],60:[function(require,module,exports){
5166+
},{"./adapters/http":30,"./adapters/localStorage":31,"./datastore":43,"./errors":59,"./utils":61}],61:[function(require,module,exports){
50425167
module.exports = [function () {
50435168
return {
50445169
isString: angular.isString,
@@ -5120,4 +5245,4 @@ module.exports = [function () {
51205245
};
51215246
}];
51225247

5123-
},{"mout/array/contains":2,"mout/array/filter":3,"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":26,"mout/object/set":27,"mout/string/makePath":28,"mout/string/upperCase":29}]},{},[59])
5248+
},{"mout/array/contains":2,"mout/array/filter":3,"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":26,"mout/object/set":27,"mout/string/makePath":28,"mout/string/upperCase":29}]},{},[60])

dist/angular-data.min.js

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

karma.start.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,20 @@ var lifecycle = {};
88

99
// Helper globals
1010
var fail = function (msg) {
11-
assert.equal('should not reach this!: ' + msg, 'failure');
11+
if (msg instanceof Error) {
12+
console.log(msg.stack);
13+
} else {
14+
assert.equal('should not reach this!: ' + msg, 'failure');
15+
}
1216
},
1317
TYPES_EXCEPT_STRING = [123, 123.123, null, undefined, {}, [], true, false, function () {
1418
}],
1519
TYPES_EXCEPT_STRING_OR_ARRAY = [123, 123.123, null, undefined, {}, true, false, function () {
1620
}],
1721
TYPES_EXCEPT_STRING_OR_OBJECT = [123, 123.123, null, undefined, [], true, false, function () {
1822
}],
23+
TYPES_EXCEPT_STRING_OR_NUMBER_OBJECT = [null, undefined, [], true, false, function () {
24+
}],
1925
TYPES_EXCEPT_ARRAY = ['string', 123, 123.123, null, undefined, {}, true, false, function () {
2026
}],
2127
TYPES_EXCEPT_STRING_OR_NUMBER = [null, undefined, {}, [], true, false, function () {

src/datastore/async_methods/index.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,16 @@ module.exports = {
4949
*/
5050
findAll: require('./findAll'),
5151

52+
/**
53+
* @doc method
54+
* @id DS.async_methods:loadRelations
55+
* @name loadRelations
56+
* @methodOf DS
57+
* @description
58+
* See [DS.loadRelations](/documentation/api/api/DS.async_methods:loadRelations).
59+
*/
60+
loadRelations: require('./loadRelations'),
61+
5262
/**
5363
* @doc method
5464
* @id DS.async_methods:refresh

0 commit comments

Comments
 (0)