Skip to content

Commit 4c48486

Browse files
committed
Add rollback behavior for resource#updateRelationship
- Catches promise failure for service#patchRelationship and resets relation id(s) - Refactor relationship assignment for adding/removing relations
1 parent 8d966a1 commit 4c48486

File tree

2 files changed

+35
-9
lines changed

2 files changed

+35
-9
lines changed

addon/models/resource.js

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -138,13 +138,33 @@ const Resource = Ember.Object.extend({
138138
139139
This is not a replace operation, but rather support for editing as a set.
140140
141+
Calling `updateRelationship` will call the service to persist the changes,
142+
via it's `patchRelationship` method. Since the default `catch` for this
143+
method is to rollback the relations, an optional `callback` function can be
144+
used to handle the error response.
145+
141146
@method updateRelationship
142147
@param {String} relation
143148
@param {Array|String|null} ids
149+
@param {Function} errorCallback `function (error) {}`
144150
*/
145-
updateRelationship(relation, ids) {
151+
updateRelationship(relation, ids, errorCallback) {
152+
let related = this.get(relation);
153+
let rollback;
154+
if (related.kind === 'hasOne') {
155+
rollback = related.get('id');
156+
} else if (related.kind === 'hasMany') {
157+
rollback = related.mapBy('id');
158+
}
146159
this._updateRelationshipsData(relation, ids);
147-
return this.get('service').patchRelationship(this, relation);
160+
return this.get('service').patchRelationship(this, relation).catch(function (error) {
161+
this._updateRelationshipsData(relation, rollback);
162+
if (typeof callback === 'function') {
163+
errorCallback(error);
164+
} else {
165+
Ember.Logger.error(error);
166+
}
167+
}.bind(this));
148168
},
149169

150170
/**
@@ -199,7 +219,7 @@ const Resource = Ember.Object.extend({
199219
/**
200220
Adds related resource identifier object to the relationship data.
201221
202-
Also sets the `content` of the related (computed property's) proxy object.
222+
Also sets or adds to the `content` of the related proxy object.
203223
204224
- For has-many relations the related identifier object is added to
205225
the resource linkage data array.
@@ -224,7 +244,10 @@ const Resource = Ember.Object.extend({
224244
if (Array.isArray(data)) {
225245
data.push(identifier);
226246
if (resource) {
227-
this.get(related).pushObject(resource);
247+
let resources = this.get(related);
248+
if (!resources.contains(resource)) {
249+
resources.pushObject(resource);
250+
}
228251
}
229252
} else {
230253
data = identifier;
@@ -260,10 +283,11 @@ const Resource = Ember.Object.extend({
260283
break;
261284
}
262285
}
263-
let type = pluralize(related);
264-
let owner = (typeof getOwner === 'function') ? getOwner(this) : this.container;
265-
let resource = owner.lookup(`service:${type}`).cacheLookup(id);
266-
this.get(related).removeObject(resource);
286+
let resources = this.get(related);
287+
let idx = resources.mapBy('id').indexOf(id);
288+
if (idx > -1) {
289+
resources.removeAt(idx);
290+
}
267291
} else if (typeof relation === 'object') {
268292
relation.data = null;
269293
this.set(`${related}.content`, null);

tests/unit/models/resource-test.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,9 @@ test('#removeRelationships', function(assert) {
296296
});
297297

298298
test('#updateRelationship', function(assert) {
299-
let serviceOp = this.sandbox.spy();
299+
let serviceOp = this.sandbox.spy(function() {
300+
return Ember.RSVP.Promise.resolve(null);
301+
});
300302
let post = this.container.lookup('model:post').create({
301303
id: '1', attributes: {title: 'Wyatt Earp', excerpt: 'Was a gambler.'},
302304
relationships: {

0 commit comments

Comments
 (0)