Skip to content

Commit 8d00ffa

Browse files
committed
Fixes #126. Closes #132.
1 parent 6e0e000 commit 8d00ffa

File tree

8 files changed

+135
-48
lines changed

8 files changed

+135
-48
lines changed

CHANGELOG.md

+5
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,14 @@
44
- #40 - Support for nested resource endpoints
55
- #118, #122 - Multiple relationships to the same model
66
- #120 - When using DSCacheFactory, allow onExpire to be specified
7+
- #132 - Inject relations for parent resource on create
8+
9+
###### Backwards compatible bug fixes
10+
- #126 - injectRelations isn't running when injecting an array
711

812
###### Other
913
- #121 - Documentation errors
14+
- #123 - Send query params with DS.find()
1015
- #124 - Documentation overhaul
1116

1217
##### 0.10.5 - 14 August 2014

dist/angular-data.js

+45-7
Original file line numberDiff line numberDiff line change
@@ -2904,6 +2904,7 @@ function loadRelations(resourceName, instance, relations, options) {
29042904
var DS = this;
29052905
var deferred = DS.$q.defer();
29062906
var promise = deferred.promise;
2907+
var definition = DS.definitions[resourceName];
29072908

29082909
try {
29092910
var IA = DS.errors.IA;
@@ -2918,7 +2919,7 @@ function loadRelations(resourceName, instance, relations, options) {
29182919
relations = [relations];
29192920
}
29202921

2921-
if (!DS.definitions[resourceName]) {
2922+
if (!definition) {
29222923
throw new DS.errors.NER(errorPrefix(resourceName) + resourceName);
29232924
} else if (!DS.utils.isObject(instance)) {
29242925
throw new IA(errorPrefix(resourceName) + 'instance(Id): Must be a string, number or object!');
@@ -2928,7 +2929,6 @@ function loadRelations(resourceName, instance, relations, options) {
29282929
throw new IA(errorPrefix(resourceName) + 'options: Must be an object!');
29292930
}
29302931

2931-
var definition = DS.definitions[resourceName];
29322932
var tasks = [];
29332933
var fields = [];
29342934

@@ -5532,21 +5532,47 @@ function _inject(definition, resource, attrs) {
55325532
return injected;
55335533
}
55345534

5535-
function _injectRelations(definition, injected) {
5535+
function _injectRelations(definition, injected, options) {
55365536
var DS = this;
55375537
DS.utils.forOwn(definition.relations, function (relatedModels, type) {
55385538
DS.utils.forOwn(relatedModels, function (defs, relationName) {
55395539
if (!DS.utils.isArray(defs)) {
55405540
defs = [defs];
55415541
}
55425542

5543-
defs.forEach(function (def) {
5543+
function _process(def, injected) {
55445544
if (DS.definitions[relationName] && injected[def.localField]) {
55455545
try {
5546-
injected[def.localField] = DS.inject(relationName, injected[def.localField]);
5546+
injected[def.localField] = DS.inject(relationName, injected[def.localField], options);
55475547
} catch (err) {
55485548
DS.$log.error(errorPrefix(definition.name) + 'Failed to inject ' + type + ' relation: "' + relationName + '"!', err);
55495549
}
5550+
} else if (options.findBelongsTo) {
5551+
if (type === 'belongsTo') {
5552+
if (DS.utils.isArray(injected)) {
5553+
DS.utils.forEach(injected, function (injectedItem) {
5554+
var parent = injectedItem[def.localKey] ? DS.get(relationName, injectedItem[def.localKey]) : null;
5555+
if (parent) {
5556+
injectedItem[def.localField] = parent;
5557+
}
5558+
});
5559+
} else {
5560+
var parent = injected[def.localKey] ? DS.get(relationName, injected[def.localKey]) : null;
5561+
if (parent) {
5562+
injected[def.localField] = parent;
5563+
}
5564+
}
5565+
}
5566+
}
5567+
}
5568+
5569+
defs.forEach(function (def) {
5570+
if (DS.utils.isArray(injected)) {
5571+
DS.utils.forEach(injected, function (injectedI) {
5572+
_process(def, injectedI);
5573+
});
5574+
} else {
5575+
_process(def, injected);
55505576
}
55515577
});
55525578
});
@@ -5598,22 +5624,34 @@ function _injectRelations(definition, injected) {
55985624
*
55995625
* @param {string} resourceName The resource type, e.g. 'user', 'comment', etc.
56005626
* @param {object|array} attrs The item or collection of items to inject into the data store.
5627+
* @param {object=} options The item or collection of items to inject into the data store. Properties:
5628+
*
5629+
* - `{boolean=}` - `findBelongsTo` - Find and attach any existing "belongsTo" relationships to the newly injected item. Default: `true`.
5630+
*
56015631
* @returns {object|array} A reference to the item that was injected into the data store or an array of references to
56025632
* the items that were injected into the data store.
56035633
*/
5604-
function inject(resourceName, attrs) {
5634+
function inject(resourceName, attrs, options) {
56055635
var DS = this;
56065636
var IA = DS.errors.IA;
56075637

5638+
options = options || {};
5639+
56085640
if (!DS.definitions[resourceName]) {
56095641
throw new DS.errors.NER(errorPrefix(resourceName) + resourceName);
56105642
} else if (!DS.utils.isObject(attrs) && !DS.utils.isArray(attrs)) {
56115643
throw new IA(errorPrefix(resourceName) + 'attrs: Must be an object or an array!');
5644+
} else if (!DS.utils.isObject(options)) {
5645+
throw new IA(errorPrefix(resourceName) + 'options: Must be an object!');
56125646
}
56135647
var definition = DS.definitions[resourceName];
56145648
var resource = DS.store[resourceName];
56155649
var injected;
56165650

5651+
if (!('findBelongsTo' in options)) {
5652+
options.findBelongsTo = true;
5653+
}
5654+
56175655
if (!DS.$rootScope.$$phase) {
56185656
DS.$rootScope.$apply(function () {
56195657
injected = _inject.call(DS, definition, resource, attrs);
@@ -5622,7 +5660,7 @@ function inject(resourceName, attrs) {
56225660
injected = _inject.call(DS, definition, resource, attrs);
56235661
}
56245662
if (definition.relations) {
5625-
_injectRelations.call(DS, definition, injected);
5663+
_injectRelations.call(DS, definition, injected, options);
56265664
}
56275665

56285666
DS.notify(definition, 'inject', injected);

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.

src/datastore/async_methods/loadRelations.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ function loadRelations(resourceName, instance, relations, options) {
5959
var DS = this;
6060
var deferred = DS.$q.defer();
6161
var promise = deferred.promise;
62+
var definition = DS.definitions[resourceName];
6263

6364
try {
6465
var IA = DS.errors.IA;
@@ -73,7 +74,7 @@ function loadRelations(resourceName, instance, relations, options) {
7374
relations = [relations];
7475
}
7576

76-
if (!DS.definitions[resourceName]) {
77+
if (!definition) {
7778
throw new DS.errors.NER(errorPrefix(resourceName) + resourceName);
7879
} else if (!DS.utils.isObject(instance)) {
7980
throw new IA(errorPrefix(resourceName) + 'instance(Id): Must be a string, number or object!');
@@ -83,7 +84,6 @@ function loadRelations(resourceName, instance, relations, options) {
8384
throw new IA(errorPrefix(resourceName) + 'options: Must be an object!');
8485
}
8586

86-
var definition = DS.definitions[resourceName];
8787
var tasks = [];
8888
var fields = [];
8989

src/datastore/sync_methods/inject.js

+43-5
Original file line numberDiff line numberDiff line change
@@ -113,21 +113,47 @@ function _inject(definition, resource, attrs) {
113113
return injected;
114114
}
115115

116-
function _injectRelations(definition, injected) {
116+
function _injectRelations(definition, injected, options) {
117117
var DS = this;
118118
DS.utils.forOwn(definition.relations, function (relatedModels, type) {
119119
DS.utils.forOwn(relatedModels, function (defs, relationName) {
120120
if (!DS.utils.isArray(defs)) {
121121
defs = [defs];
122122
}
123123

124-
defs.forEach(function (def) {
124+
function _process(def, injected) {
125125
if (DS.definitions[relationName] && injected[def.localField]) {
126126
try {
127-
injected[def.localField] = DS.inject(relationName, injected[def.localField]);
127+
injected[def.localField] = DS.inject(relationName, injected[def.localField], options);
128128
} catch (err) {
129129
DS.$log.error(errorPrefix(definition.name) + 'Failed to inject ' + type + ' relation: "' + relationName + '"!', err);
130130
}
131+
} else if (options.findBelongsTo) {
132+
if (type === 'belongsTo') {
133+
if (DS.utils.isArray(injected)) {
134+
DS.utils.forEach(injected, function (injectedItem) {
135+
var parent = injectedItem[def.localKey] ? DS.get(relationName, injectedItem[def.localKey]) : null;
136+
if (parent) {
137+
injectedItem[def.localField] = parent;
138+
}
139+
});
140+
} else {
141+
var parent = injected[def.localKey] ? DS.get(relationName, injected[def.localKey]) : null;
142+
if (parent) {
143+
injected[def.localField] = parent;
144+
}
145+
}
146+
}
147+
}
148+
}
149+
150+
defs.forEach(function (def) {
151+
if (DS.utils.isArray(injected)) {
152+
DS.utils.forEach(injected, function (injectedI) {
153+
_process(def, injectedI);
154+
});
155+
} else {
156+
_process(def, injected);
131157
}
132158
});
133159
});
@@ -179,22 +205,34 @@ function _injectRelations(definition, injected) {
179205
*
180206
* @param {string} resourceName The resource type, e.g. 'user', 'comment', etc.
181207
* @param {object|array} attrs The item or collection of items to inject into the data store.
208+
* @param {object=} options The item or collection of items to inject into the data store. Properties:
209+
*
210+
* - `{boolean=}` - `findBelongsTo` - Find and attach any existing "belongsTo" relationships to the newly injected item. Default: `true`.
211+
*
182212
* @returns {object|array} A reference to the item that was injected into the data store or an array of references to
183213
* the items that were injected into the data store.
184214
*/
185-
function inject(resourceName, attrs) {
215+
function inject(resourceName, attrs, options) {
186216
var DS = this;
187217
var IA = DS.errors.IA;
188218

219+
options = options || {};
220+
189221
if (!DS.definitions[resourceName]) {
190222
throw new DS.errors.NER(errorPrefix(resourceName) + resourceName);
191223
} else if (!DS.utils.isObject(attrs) && !DS.utils.isArray(attrs)) {
192224
throw new IA(errorPrefix(resourceName) + 'attrs: Must be an object or an array!');
225+
} else if (!DS.utils.isObject(options)) {
226+
throw new IA(errorPrefix(resourceName) + 'options: Must be an object!');
193227
}
194228
var definition = DS.definitions[resourceName];
195229
var resource = DS.store[resourceName];
196230
var injected;
197231

232+
if (!('findBelongsTo' in options)) {
233+
options.findBelongsTo = true;
234+
}
235+
198236
if (!DS.$rootScope.$$phase) {
199237
DS.$rootScope.$apply(function () {
200238
injected = _inject.call(DS, definition, resource, attrs);
@@ -203,7 +241,7 @@ function inject(resourceName, attrs) {
203241
injected = _inject.call(DS, definition, resource, attrs);
204242
}
205243
if (definition.relations) {
206-
_injectRelations.call(DS, definition, injected);
244+
_injectRelations.call(DS, definition, injected, options);
207245
}
208246

209247
DS.notify(definition, 'inject', injected);

test/integration/datastore/async_methods/create.test.js

+5-7
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ describe('DS.create(resourceName, attrs[, options])', function () {
115115
116116
}
117117
}).then(function (user) {
118-
assert.deepEqual(user, payload, 'user should have been created');
118+
assert.deepEqual(user.id, payload.id, 'user should have been created');
119119

120120
DS.find('user', 99); // should not trigger another http request
121121
}, function (err) {
@@ -131,12 +131,10 @@ describe('DS.create(resourceName, attrs[, options])', function () {
131131
assert.equal(lifecycle.afterInject.callCount, 2, 'afterInject should have been called twice');
132132
assert.equal(lifecycle.serialize.callCount, 1, 'serialize should have been called');
133133
assert.equal(lifecycle.deserialize.callCount, 1, 'deserialize should have been called');
134-
assert.deepEqual(DS.get('user', 99), payload);
135-
assert.deepEqual(DS.get('profile', 999), {
136-
id: 999,
137-
userId: 99,
138-
139-
});
134+
assert.deepEqual(DS.get('user', 99).id, payload.id);
135+
assert.isObject(DS.get('user', 99).profile);
136+
assert.deepEqual(DS.get('profile', 999).id, 999);
137+
assert.isObject(DS.get('profile', 999).user);
140138
});
141139
it('should handle nested resources', function () {
142140
var testComment = {

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

+8-7
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,14 @@ describe('DS.loadRelations(resourceName, instance(Id), relations[, options]): ',
5959
$httpBackend.expectGET('http://test.angular-cache.com/profile?userId=10').respond(200, profile15);
6060

6161
DS.loadRelations('user', 10, ['comment', 'profile', 'organization'], { params: { approvedBy: 10 } }).then(function (user) {
62-
assert.deepEqual(user.comments, [
63-
comment11,
64-
comment12,
65-
comment13
66-
]);
67-
assert.deepEqual(user.organization, organization14);
68-
assert.deepEqual(user.profile, profile15);
62+
assert.deepEqual(user.comments[0].id, DS.get('comment', user.comments[0].id).id);
63+
assert.deepEqual(user.comments[0].user, DS.get('comment', user.comments[0].id).user);
64+
assert.deepEqual(user.comments[1].id, DS.get('comment', user.comments[1].id).id);
65+
assert.deepEqual(user.comments[1].user, DS.get('comment', user.comments[1].id).user);
66+
assert.deepEqual(user.comments[2].id, DS.get('comment', user.comments[2].id).id);
67+
assert.deepEqual(user.comments[2].user, DS.get('comment', user.comments[2].id).user);
68+
assert.deepEqual(user.organization.id, DS.get('organization', 14).id);
69+
assert.deepEqual(user.profile.id, DS.get('profile', 15).id);
6970
}, fail);
7071

7172
$httpBackend.flush();

test/integration/datastore/sync_methods/inject.test.js

+25-18
Original file line numberDiff line numberDiff line change
@@ -156,38 +156,45 @@ describe('DS.inject(resourceName, attrs)', function () {
156156

157157
assert.deepEqual(DS.get('user', 1), user1);
158158
assert.deepEqual(DS.get('organization', 2), organization2);
159-
assert.deepEqual(DS.get('comment', 3), comment3);
160-
assert.deepEqual(DS.get('profile', 4), profile4);
159+
assert.deepEqual(DS.get('comment', 3).id, comment3.id);
160+
assert.deepEqual(DS.get('profile', 4).id, profile4.id);
161161

162162
// can inject items with relations
163-
DS.inject('user', user10);
163+
DS.inject('user', user10, 0);
164164
DS.inject('organization', organization15);
165165
DS.inject('comment', comment19);
166166
DS.inject('profile', profile21);
167167

168168
// originals
169-
assert.deepEqual(DS.get('user', 10), user10);
170-
assert.deepEqual(DS.get('organization', 15), organization15);
171-
assert.deepEqual(DS.get('comment', 19), comment19);
172-
assert.deepEqual(DS.get('profile', 21), profile21);
169+
assert.equal(DS.get('user', 10).name, user10.name);
170+
assert.equal(DS.get('user', 10).id, user10.id);
171+
assert.equal(DS.get('user', 10).organizationId, user10.organizationId);
172+
assert.isArray(DS.get('user', 10).comments);
173+
assert.deepEqual(DS.get('organization', 15).name, organization15.name);
174+
assert.deepEqual(DS.get('organization', 15).id, organization15.id);
175+
assert.isArray(DS.get('organization', 15).users);
176+
assert.deepEqual(DS.get('comment', 19).id, comment19.id);
177+
assert.deepEqual(DS.get('comment', 19).content, comment19.content);
178+
assert.deepEqual(DS.get('profile', 21).id, profile21.id);
179+
assert.deepEqual(DS.get('profile', 21).content, profile21.content);
173180

174181
// user10 relations
175-
assert.deepEqual(DS.get('comment', 11), comment11);
176-
assert.deepEqual(DS.get('comment', 12), comment12);
177-
assert.deepEqual(DS.get('comment', 13), comment13);
178-
assert.deepEqual(DS.get('organization', 14), organization14);
179-
assert.deepEqual(DS.get('profile', 15), profile15);
182+
assert.deepEqual(DS.get('comment', 11), DS.get('user', 10).comments[0]);
183+
assert.deepEqual(DS.get('comment', 12), DS.get('user', 10).comments[1]);
184+
assert.deepEqual(DS.get('comment', 13), DS.get('user', 10).comments[2]);
185+
assert.deepEqual(DS.get('organization', 14), DS.get('user', 10).organization);
186+
assert.deepEqual(DS.get('profile', 15), DS.get('user', 10).profile);
180187

181188
// organization15 relations
182-
assert.deepEqual(DS.get('user', 16), user16);
183-
assert.deepEqual(DS.get('user', 17), user17);
184-
assert.deepEqual(DS.get('user', 18), user18);
189+
assert.deepEqual(DS.get('user', 16), DS.get('organization', 15).users[0]);
190+
assert.deepEqual(DS.get('user', 17), DS.get('organization', 15).users[1]);
191+
assert.deepEqual(DS.get('user', 18), DS.get('organization', 15).users[2]);
185192

186193
// comment19 relations
187-
assert.deepEqual(DS.get('user', 20), user20);
188-
assert.deepEqual(DS.get('user', 19), user19);
194+
assert.deepEqual(DS.get('user', 20), DS.get('comment', 19).user);
195+
assert.deepEqual(DS.get('user', 19), DS.get('comment', 19).approvedByUser);
189196

190197
// profile21 relations
191-
assert.deepEqual(DS.get('user', 22), user22);
198+
assert.deepEqual(DS.get('user', 22), DS.get('profile', 21).user);
192199
});
193200
});

0 commit comments

Comments
 (0)