From 0b0f6dc3760fb89c5750563fd9061b54adc69cbc Mon Sep 17 00:00:00 2001 From: Andy Brown Date: Mon, 17 Aug 2015 09:15:57 -0700 Subject: [PATCH] default to array when update keys are integers --- lib/update.js | 10 +++------- lib/util/defaultObject.js | 35 +++++++++++++++++++++++++++++++++++ lib/util/isEmpty.js | 5 +++++ test/updateIn-spec.js | 6 ++++++ test/updeep-spec.js | 12 ++++++++++++ 5 files changed, 61 insertions(+), 7 deletions(-) create mode 100644 lib/util/defaultObject.js create mode 100644 lib/util/isEmpty.js diff --git a/lib/update.js b/lib/update.js index 5ea4e62..e1c3dc3 100644 --- a/lib/update.js +++ b/lib/update.js @@ -1,8 +1,6 @@ import wrap from './wrap'; - -function isEmpty(object) { - return !Object.keys(object).length; -} +import isEmpty from './util/isEmpty'; +import defaultObject from './util/defaultObject'; function reduce(object, callback, initialValue) { return Object.keys(object).reduce((acc, key) => { @@ -64,9 +62,7 @@ function update(updates, object, ...args) { return updates; } - const defaultedObject = (typeof object === 'undefined' || object === null) ? - {} : - object; + const defaultedObject = defaultObject(object, updates); const resolvedUpdates = resolveUpdates(updates, defaultedObject); diff --git a/lib/util/defaultObject.js b/lib/util/defaultObject.js new file mode 100644 index 0000000..be6286f --- /dev/null +++ b/lib/util/defaultObject.js @@ -0,0 +1,35 @@ +import isEmpty from './isEmpty'; + +function isInt(value) { + if (isNaN(value)) { + return false; + } + const x = parseFloat(value); + return (x | 0) === x; +} + +function isArrayUpdate(updates) { + for (const updateKey of Object.keys(updates)) { + if (!isInt(updateKey)) { return false; } + } + + return true; +} + +function arrayOrObject(updates) { + if (!isEmpty(updates) && isArrayUpdate(updates)) { + return []; + } + + return {}; +} + +function defaultObject(object, updates) { + if (typeof object === 'undefined' || object === null) { + return arrayOrObject(updates); + } + + return object; +} + +export default defaultObject; diff --git a/lib/util/isEmpty.js b/lib/util/isEmpty.js new file mode 100644 index 0000000..4e27ba2 --- /dev/null +++ b/lib/util/isEmpty.js @@ -0,0 +1,5 @@ +function isEmpty(object) { + return !Object.keys(object).length; +} + +export default isEmpty; diff --git a/test/updateIn-spec.js b/test/updateIn-spec.js index 6c15fb3..6f9b73a 100644 --- a/test/updateIn-spec.js +++ b/test/updateIn-spec.js @@ -27,6 +27,12 @@ describe('u.updateIn', () => { expect(result).to.eql({ a: [0, 3, 0] }); }); + it('can create array if all keys are numbers', () => { + const result = u.updateIn('a.0', 3, null); + + expect(result).to.eql({ a: [3] }); + }); + it('can be partially applied', () => { const object = { a: { b: 0 } }; const result = u.updateIn('a.b')(3)(object); diff --git a/test/updeep-spec.js b/test/updeep-spec.js index 36c17e5..bbfb4b9 100644 --- a/test/updeep-spec.js +++ b/test/updeep-spec.js @@ -42,6 +42,18 @@ describe('updeep', () => { expect(u(null, {})).to.be.null; }); + it('can create array if all keys are numbers', () => { + const result = u({ 0: 'hi', '1': 'world' }, null); + + expect(result).to.eql(['hi', 'world']); + }); + + it('does not create array if any key is not number', () => { + const result = u({ 0: 'hi', '1a': 'world' }, null); + + expect(result).to.eql({ 0: 'hi', '1a': 'world' }); + }); + it('can add an element to an array', () => { const object = []; const result = u({ 0: 3 }, object);