Skip to content

Commit fd068a6

Browse files
committed
bugfix (get-updates): update solution for separating the two update operations.
1 parent 288b65c commit fd068a6

File tree

3 files changed

+77
-12
lines changed

3 files changed

+77
-12
lines changed

lib/get-updates.js

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -116,13 +116,12 @@
116116
if (_.isDate(srcValue) && _.isDate(dstValue)) {
117117
if (srcValue.getTime() != dstValue.getTime()) diff[k] = dstValue;
118118
}
119-
else if (_.isArray(srcValue) && _.isArray(dstValue) && !angular.equals(srcValue, dstValue)) {
120-
diff[k] = dstValue;
121-
}
122-
else if (_.isObject(srcValue) && _.isObject(dstValue)) {
119+
120+
if (_.isObject(srcValue) && _.isObject(dstValue)) {
123121
var valueDiff = getDifference(srcValue, dstValue);
124122
utils.setFilled(diff, k, valueDiff);
125123
}
124+
126125
else if (srcValue !== dstValue) {
127126
diff[k] = dstValue;
128127
}
@@ -144,10 +143,12 @@
144143

145144
var set = createSet(paths);
146145
var unset = createUnset(paths);
146+
var pull = createPull(unset);
147147

148148
var updates = {};
149149
utils.setFilled(updates, '$set', set);
150150
utils.setFilled(updates, '$unset', unset);
151+
utils.setFilled(updates, '$pull', pull);
151152

152153
return updates;
153154
};
@@ -167,6 +168,18 @@
167168
}, {});
168169
};
169170

171+
var createPull = function(unset) {
172+
var arrKeyPaths = _.keys(unset).map(function(k) {
173+
var split = k.match(/(.*)\.\d+$/);
174+
return split && split[1];
175+
});
176+
177+
return _.compact(arrKeyPaths).reduce(function(pull, k) {
178+
pull[k] = null;
179+
return pull;
180+
}, {});
181+
};
182+
170183
var getUndefinedKeys = function(obj) {
171184
return _.keys(obj).filter(function (k) {
172185
var v = obj[k];

modules/angular-meteor-object.js

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,19 @@ angularMeteorObject.factory('AngularMeteorObject', [
5656
}
5757
}
5858

59-
// NOTE: do not use #upsert() method, since it does not exist in some collections
60-
collection.update(this.$$id, mods, createFulfill({ action: 'updated' }));
59+
var pullUpdate;
60+
if (mods.$pull) {
61+
pullUpdate = { $pull : mods.$pull };
62+
}
63+
64+
if (!pullUpdate) {
65+
// NOTE: do not use #upsert() method, since it does not exist in some collections
66+
collection.update(this.$$id, mods, createFulfill({action: 'updated'}));
67+
}
68+
else {
69+
collection.update(this.$$id, mods);
70+
collection.update(this.$$id, pullUpdate, createFulfill({action: 'updated'}))
71+
}
6172
}
6273
// insert
6374
else {
@@ -70,7 +81,7 @@ angularMeteorObject.factory('AngularMeteorObject', [
7081
collection.insert(mods, createFulfill({ action: 'inserted' }));
7182
}
7283

73-
return deferred.promise;
84+
return deferred.promise;
7485
};
7586

7687
AngularMeteorObject.reset = function(keepClientProps) {
@@ -102,7 +113,7 @@ angularMeteorObject.factory('AngularMeteorObject', [
102113
delete self[prop];
103114
delete self._serverBackup[prop];
104115
});
105-
}
116+
}
106117

107118
else {
108119
_.keys(this.getRawObject()).forEach(function(prop) {
@@ -159,16 +170,28 @@ angularMeteorObject.factory('$meteorObject', [
159170
this.unregisterAutoBind = this._auto && $rootScope.$watch(function(){
160171
return self.getRawObject();
161172
}, function (item, oldItem) {
162-
if (item === oldItem) return;
173+
if (item === oldItem) {
174+
self.$$collection.update({_id: item._id}, self.getRawObject());
175+
return;
176+
}
163177

164178
var id = item._id;
165179
delete item._id;
166180
delete oldItem._id;
167181

168182
var updates = getUpdates(oldItem, item);
169183
if (_.isEmpty(updates)) return;
184+
var pullUpdate;
170185

186+
if (updates.$pull) {
187+
pullUpdate = { $pull : updates.$pull };
188+
delete updates.$pull;
189+
}
171190
self.$$collection.update({_id: id}, updates);
191+
192+
if (pullUpdate) {
193+
self.$$collection.update({ _id : id}, pullUpdate);
194+
}
172195
}, true);
173196

174197
this.unregisterAutoDestroy = $rootScope.$on('$destroy', function() {

tests/integration/angular-meteor-get-updates-spec.js

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ describe('getUpdates module', function() {
4545
var expectedUpdates = {
4646
$set: {
4747
'b.e': 'e',
48-
'd' : [1,2,4,3]
48+
'd.2': 4,
49+
'd.3': 3
4950
}
5051
};
5152

@@ -79,6 +80,30 @@ describe('getUpdates module', function() {
7980
expect(actualUpdates).toDeepEqual(expectedUpdates);
8081
});
8182

83+
it('should define a "$pull" property when the destination object has an array value with missing elements', function() {
84+
var src = {
85+
arr: [1, 2, 3, 4, 5]
86+
};
87+
88+
var dst = {
89+
arr: [1, 2, 3]
90+
};
91+
92+
var expectedUpdates = {
93+
$unset: {
94+
'arr.3': true,
95+
'arr.4': true
96+
},
97+
98+
$pull: {
99+
'arr': null
100+
}
101+
};
102+
103+
var actualUpdates = getUpdates(src, dst);
104+
expect(actualUpdates).toDeepEqual(expectedUpdates);
105+
});
106+
82107
it('should get updates when object-field is assigned a deep-object', function() {
83108
var src = {a: {}};
84109
var dst = {a: {L1: {L2: {L3: 'v'}}}};
@@ -158,7 +183,9 @@ describe('getUpdates module', function() {
158183

159184
expect(updates).toDeepEqual({
160185
$set: {
161-
'a': [1,2,3],
186+
'a.0': 1,
187+
'a.1': 2,
188+
'a.2': 3
162189
}
163190
});
164191
});
@@ -206,7 +233,9 @@ describe('getUpdates module', function() {
206233

207234
expect(updates).toDeepEqual({
208235
$set: {
209-
'a.subfield': [1,2,3],
236+
'a.subfield.0': 1,
237+
'a.subfield.1': 2,
238+
'a.subfield.2': 3
210239
}
211240
});
212241
});

0 commit comments

Comments
 (0)