Skip to content

Commit 7c9b36f

Browse files
committed
Fixes #135.
1 parent d62127f commit 7c9b36f

File tree

10 files changed

+129
-41
lines changed

10 files changed

+129
-41
lines changed

CHANGELOG.md

+5
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
##### 1.0.0-beta.2 - xx August 2014
2+
3+
###### Backwards compatible bug fixes
4+
- #135 - loadrelations loop
5+
16
##### 1.0.0-beta.1 - 23 August 2014
27

38
###### Backwards compatible API changes

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ Unlike Backbone and Ember Models, angular-data does not require the use of gette
99
Supporting relations, computed properties, model lifecycle control and a slew of other features, angular-data is the tool for giving your data the respect it deserves.
1010

1111
__Latest Release:__ [1.0.0-beta.1](http://angular-data.pseudobry.com/)
12-
__master:__ [1.0.0-beta.1](http://angular-data-next.pseudobry.com/)
12+
__master:__ [1.0.0-beta.2](http://angular-data-next.pseudobry.com/)
1313

1414
Angular-data is in a 1.0.0 Beta. The API is rather stable and angular-data is well tested.
1515

bower.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"author": "Jason Dobry",
33
"name": "angular-data",
44
"description": "Data store for Angular.js.",
5-
"version": "1.0.0-beta.1",
5+
"version": "1.0.0-beta.2",
66
"homepage": "http://angular-data.pseudobry.com/",
77
"repository": {
88
"type": "git",

dist/angular-data.js

+37-18
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/**
22
* @author Jason Dobry <[email protected]>
33
* @file angular-data.js
4-
* @version 1.0.0-beta.1 - Homepage <http://angular-data.pseudobry.com/>
4+
* @version 1.0.0-beta.2 - Homepage <http://angular-data.pseudobry.com/>
55
* @copyright (c) 2014 Jason Dobry <https://github.com/jmdobry/>
66
* @license MIT <https://github.com/jmdobry/angular-data/blob/master/LICENSE>
77
*
@@ -5418,6 +5418,11 @@ module.exports = {
54185418

54195419
},{"./bindAll":50,"./bindOne":51,"./changes":52,"./createInstance":53,"./defineResource":54,"./digest":55,"./eject":56,"./ejectAll":57,"./filter":58,"./get":59,"./hasChanges":60,"./inject":62,"./lastModified":63,"./lastSaved":64,"./previous":65}],62:[function(require,module,exports){
54205420
var observe = require('../../../lib/observe-js/observe-js');
5421+
var stack = 0;
5422+
var data = {
5423+
injectedSoFar: {}
5424+
};
5425+
54215426
function errorPrefix(resourceName) {
54225427
return 'DS.inject(' + resourceName + ', attrs[, options]): ';
54235428
}
@@ -5532,7 +5537,7 @@ function _inject(definition, resource, attrs) {
55325537
return injected;
55335538
}
55345539

5535-
function _injectRelations(definition, injected, options) {
5540+
function _injectRelations(definition, injected, options, injectedSoFar) {
55365541
var DS = this;
55375542
DS.utils.forOwn(definition.relations, function (relatedModels, type) {
55385543
DS.utils.forOwn(relatedModels, function (defs, relationName) {
@@ -5541,9 +5546,10 @@ function _injectRelations(definition, injected, options) {
55415546
}
55425547

55435548
function _process(def, injected) {
5544-
if (DS.definitions[relationName] && injected[def.localField]) {
5549+
if (DS.definitions[relationName] && injected[def.localField] && !injectedSoFar[relationName + injected[def.localField][DS.definitions[relationName].idAttribute]]) {
55455550
try {
5546-
injected[def.localField] = DS.inject(relationName, injected[def.localField], options);
5551+
injectedSoFar[relationName + injected[def.localField][DS.definitions[relationName].idAttribute]] = 1;
5552+
injected[def.localField] = DS.inject(relationName, injected[def.localField], options, injectedSoFar);
55475553
} catch (err) {
55485554
DS.$log.error(errorPrefix(definition.name) + 'Failed to inject ' + type + ' relation: "' + relationName + '"!', err);
55495555
}
@@ -5631,39 +5637,52 @@ function _injectRelations(definition, injected, options) {
56315637
* @returns {object|array} A reference to the item that was injected into the data store or an array of references to
56325638
* the items that were injected into the data store.
56335639
*/
5634-
function inject(resourceName, attrs, options) {
5640+
function inject(resourceName, attrs, options, injectedSoFar) {
56355641
var DS = this;
56365642
var IA = DS.errors.IA;
5643+
var definition = DS.definitions[resourceName];
56375644

56385645
options = options || {};
56395646

5640-
if (!DS.definitions[resourceName]) {
5647+
if (!definition) {
56415648
throw new DS.errors.NER(errorPrefix(resourceName) + resourceName);
56425649
} else if (!DS.utils.isObject(attrs) && !DS.utils.isArray(attrs)) {
56435650
throw new IA(errorPrefix(resourceName) + 'attrs: Must be an object or an array!');
56445651
} else if (!DS.utils.isObject(options)) {
56455652
throw new IA(errorPrefix(resourceName) + 'options: Must be an object!');
56465653
}
5647-
var definition = DS.definitions[resourceName];
56485654
var resource = DS.store[resourceName];
56495655
var injected;
56505656

56515657
if (!('findBelongsTo' in options)) {
56525658
options.findBelongsTo = true;
56535659
}
56545660

5655-
if (!DS.$rootScope.$$phase) {
5656-
DS.$rootScope.$apply(function () {
5657-
injected = _inject.call(DS, definition, resource, attrs);
5658-
});
5659-
} else {
5660-
injected = _inject.call(DS, definition, resource, attrs);
5661-
}
5662-
if (definition.relations) {
5663-
_injectRelations.call(DS, definition, injected, options);
5661+
stack++;
5662+
5663+
try {
5664+
if (!DS.$rootScope.$$phase) {
5665+
DS.$rootScope.$apply(function () {
5666+
injected = _inject.call(DS, definition, resource, attrs, injectedSoFar || data.injectedSoFar);
5667+
});
5668+
} else {
5669+
injected = _inject.call(DS, definition, resource, attrs, injectedSoFar || data.injectedSoFar);
5670+
}
5671+
if (definition.relations) {
5672+
_injectRelations.call(DS, definition, injected, options, injectedSoFar || data.injectedSoFar);
5673+
}
5674+
5675+
DS.notify(definition, 'inject', injected);
5676+
5677+
stack--;
5678+
} catch (err) {
5679+
stack--;
5680+
throw err;
56645681
}
56655682

5666-
DS.notify(definition, 'inject', injected);
5683+
if (!stack) {
5684+
data.injectedSoFar = {};
5685+
}
56675686

56685687
return injected;
56695688
}
@@ -5986,7 +6005,7 @@ module.exports = [function () {
59866005
* @id angular-data
59876006
* @name angular-data
59886007
* @description
5989-
* __Version:__ 1.0.0-beta.1
6008+
* __Version:__ 1.0.0-beta.2
59906009
*
59916010
* ## Install
59926011
*

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.

guide/nav.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@
8282
<i class="icon-wrench icon-white"></i> API <b class="caret"></b>
8383
</a>
8484
<ul class="dropdown-menu">
85-
<li class="nav-header">Angular-data - 1.0.0-beta.1</li>
85+
<li class="nav-header">Angular-data - 1.0.0-beta.2</li>
8686
<li>
8787
<a href="/documentation/api/angular-data/angular-data">Overview</a>
8888
</li>

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "angular-data",
33
"description": "Data store for Angular.js.",
4-
"version": "1.0.0-beta.1",
4+
"version": "1.0.0-beta.2",
55
"homepage": "http://angular-data.pseudobry.com",
66
"repository": {
77
"type": "git",

src/datastore/sync_methods/inject.js

+35-16
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
var observe = require('../../../lib/observe-js/observe-js');
2+
var stack = 0;
3+
var data = {
4+
injectedSoFar: {}
5+
};
6+
27
function errorPrefix(resourceName) {
38
return 'DS.inject(' + resourceName + ', attrs[, options]): ';
49
}
@@ -113,7 +118,7 @@ function _inject(definition, resource, attrs) {
113118
return injected;
114119
}
115120

116-
function _injectRelations(definition, injected, options) {
121+
function _injectRelations(definition, injected, options, injectedSoFar) {
117122
var DS = this;
118123
DS.utils.forOwn(definition.relations, function (relatedModels, type) {
119124
DS.utils.forOwn(relatedModels, function (defs, relationName) {
@@ -122,9 +127,10 @@ function _injectRelations(definition, injected, options) {
122127
}
123128

124129
function _process(def, injected) {
125-
if (DS.definitions[relationName] && injected[def.localField]) {
130+
if (DS.definitions[relationName] && injected[def.localField] && !injectedSoFar[relationName + injected[def.localField][DS.definitions[relationName].idAttribute]]) {
126131
try {
127-
injected[def.localField] = DS.inject(relationName, injected[def.localField], options);
132+
injectedSoFar[relationName + injected[def.localField][DS.definitions[relationName].idAttribute]] = 1;
133+
injected[def.localField] = DS.inject(relationName, injected[def.localField], options, injectedSoFar);
128134
} catch (err) {
129135
DS.$log.error(errorPrefix(definition.name) + 'Failed to inject ' + type + ' relation: "' + relationName + '"!', err);
130136
}
@@ -212,39 +218,52 @@ function _injectRelations(definition, injected, options) {
212218
* @returns {object|array} A reference to the item that was injected into the data store or an array of references to
213219
* the items that were injected into the data store.
214220
*/
215-
function inject(resourceName, attrs, options) {
221+
function inject(resourceName, attrs, options, injectedSoFar) {
216222
var DS = this;
217223
var IA = DS.errors.IA;
224+
var definition = DS.definitions[resourceName];
218225

219226
options = options || {};
220227

221-
if (!DS.definitions[resourceName]) {
228+
if (!definition) {
222229
throw new DS.errors.NER(errorPrefix(resourceName) + resourceName);
223230
} else if (!DS.utils.isObject(attrs) && !DS.utils.isArray(attrs)) {
224231
throw new IA(errorPrefix(resourceName) + 'attrs: Must be an object or an array!');
225232
} else if (!DS.utils.isObject(options)) {
226233
throw new IA(errorPrefix(resourceName) + 'options: Must be an object!');
227234
}
228-
var definition = DS.definitions[resourceName];
229235
var resource = DS.store[resourceName];
230236
var injected;
231237

232238
if (!('findBelongsTo' in options)) {
233239
options.findBelongsTo = true;
234240
}
235241

236-
if (!DS.$rootScope.$$phase) {
237-
DS.$rootScope.$apply(function () {
238-
injected = _inject.call(DS, definition, resource, attrs);
239-
});
240-
} else {
241-
injected = _inject.call(DS, definition, resource, attrs);
242-
}
243-
if (definition.relations) {
244-
_injectRelations.call(DS, definition, injected, options);
242+
stack++;
243+
244+
try {
245+
if (!DS.$rootScope.$$phase) {
246+
DS.$rootScope.$apply(function () {
247+
injected = _inject.call(DS, definition, resource, attrs, injectedSoFar || data.injectedSoFar);
248+
});
249+
} else {
250+
injected = _inject.call(DS, definition, resource, attrs, injectedSoFar || data.injectedSoFar);
251+
}
252+
if (definition.relations) {
253+
_injectRelations.call(DS, definition, injected, options, injectedSoFar || data.injectedSoFar);
254+
}
255+
256+
DS.notify(definition, 'inject', injected);
257+
258+
stack--;
259+
} catch (err) {
260+
stack--;
261+
throw err;
245262
}
246263

247-
DS.notify(definition, 'inject', injected);
264+
if (!stack) {
265+
data.injectedSoFar = {};
266+
}
248267

249268
return injected;
250269
}

src/index.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* @id angular-data
77
* @name angular-data
88
* @description
9-
* __Version:__ 1.0.0-beta.1
9+
* __Version:__ 1.0.0-beta.2
1010
*
1111
* ## Install
1212
*

test/integration/datastore/async_methods/loadRelations.test.js

+45
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,51 @@ describe('DS.loadRelations(resourceName, instance(Id), relations[, options]): ',
159159
fail('Should not have succeeded!');
160160
});
161161

162+
$httpBackend.flush();
163+
});
164+
it('should handle multiple belongsTo levels when the response includes nested resources', function () {
165+
var organization = DS.inject('organization', {
166+
id: 1
167+
});
168+
169+
$httpBackend.expectGET('http://test.angular-cache.com/organization/1/user').respond(200, [
170+
{
171+
organizationId: 1,
172+
id: 1
173+
}
174+
]);
175+
176+
DS.loadRelations('organization', organization, ['user']).then(function (organization) {
177+
assert.isTrue(organization === organization.users[0].organization);
178+
179+
$httpBackend.expectGET('http://test.angular-cache.com/user/1/comment').respond(200, [
180+
{
181+
id: 1,
182+
userId: 1,
183+
user: {
184+
id: 1
185+
}
186+
},
187+
{
188+
id: 2,
189+
userId: 1,
190+
user: {
191+
id: 1
192+
}
193+
}
194+
]);
195+
196+
var user = DS.get('user', 1);
197+
198+
DS.loadRelations('user', user, ['comment']).then(function (user) {
199+
assert.isArray(user.comments);
200+
}, function () {
201+
fail('Should not have succeeded!');
202+
});
203+
}, function () {
204+
fail('Should not have succeeded!');
205+
});
206+
162207
$httpBackend.flush();
163208
});
164209
});

0 commit comments

Comments
 (0)