Skip to content

Commit c70a34c

Browse files
Allow setValueForKeyPath to create missing intermediate paths.
1 parent af5d975 commit c70a34c

2 files changed

Lines changed: 57 additions & 6 deletions

File tree

lib/underscore-keypath.js

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -212,16 +212,32 @@
212212

213213
setValueForKeyPath : function (obj, keypath, newValue) {
214214
"use strict";
215+
216+
var createTarget = function( obj, segments ) {
217+
var i, target;
218+
for( i = 0; i < segments.length; i += 1 ) {
219+
if( underscore.hasKeyPath( obj, segments.slice( 0, i + 1 ) ) ) {
220+
continue;
221+
}
222+
if( i === 0 ) {
223+
setProperty(obj, segments[ 0 ], {} );
224+
continue;
225+
}
226+
target = underscore.valueForKeyPath( obj, segments.slice( 0, i ) );
227+
setProperty(target, segments[ i ], {} );
228+
}
229+
};
230+
215231
var segments = toSegments(keypath), lastPropertyName, target;
216232

217233
lastPropertyName = segments.pop();
218-
target = underscore(obj).valueForKeyPath(segments.join("."));
219-
220-
if (target !== null && target !== undefined) {
221-
return setProperty(target, lastPropertyName, newValue);
234+
target = underscore(obj).valueForKeyPath(segments);
235+
236+
if (target === null || target === undefined) {
237+
createTarget( obj, segments );
238+
target = underscore(obj).valueForKeyPath(segments);
222239
}
223-
224-
return undefined;
240+
return setProperty(target, lastPropertyName, newValue);
225241
},
226242

227243
pluckByKeyPath : function (array, keypath) {

test/setValueForKeyPath.js

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,39 @@ describe("setValueForKeyPath", function () {
4040
fixture.bar._age.should.be.exactly(99);
4141
});
4242
});
43+
44+
describe("set property when target missing", function () {
45+
it("new path two deep must work", function () {
46+
_(fixture).setValueForKeyPath("a.b", 2)
47+
.should.be.exactly(2);
48+
fixture.a.b.should.be.exactly(2);
49+
});
50+
51+
it("new path three deep must work", function () {
52+
_(fixture).setValueForKeyPath("c.d.e", 3)
53+
.should.be.exactly(3);
54+
fixture.c.d.e.should.be.exactly(3);
55+
});
56+
57+
it("new path four deep must work", function () {
58+
_(fixture).setValueForKeyPath("f.g.h.i", 4)
59+
.should.be.exactly(4);
60+
fixture.f.g.h.i.should.be.exactly(4);
61+
});
62+
63+
it("new path three deep, down one must work", function () {
64+
_(fixture).setValueForKeyPath("a.m.n.o", 5)
65+
.should.be.exactly(5);
66+
fixture.a.m.n.o.should.be.exactly(5);
67+
});
68+
69+
it("new path three deep, down two must work", function () {
70+
_(fixture).setValueForKeyPath("a.b.p.q.r", 6)
71+
.should.be.exactly(6);
72+
fixture.a.b.p.q.r.should.be.exactly(6);
73+
});
74+
75+
});
76+
77+
4378
});

0 commit comments

Comments
 (0)