diff --git a/CHANGELOG.md b/CHANGELOG.md index 348f756..b9ce4b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Change Log ## [unreleased] -* Add `u.if` to conditionally update objects. +* Add `u.if` and `u.ifElse` to conditionally update objects. * Add `u.map` to update all values in an array or object. * Replace object outright if null or constant provided as `updates`. * Freeze objects returned by helper methods that use `update` like `withDefault`, `map`, `in`, etc. Previously, only `u` did freezing. diff --git a/README.md b/README.md index a4fa90c..e9f26df 100644 --- a/README.md +++ b/README.md @@ -140,7 +140,7 @@ u({ ### `u.if(predicate(, updates)(, object))` -Apply updates only if `predicate` is truthy or, if `predicate` is a function, +Apply `updates` only if `predicate` is truthy or, if `predicate` is a function, it evaluates to truthy when called with `object`. ```js @@ -154,6 +154,23 @@ u({ // => { a: 3 } ``` +### `u.ifElse(predicate(, trueUpdates)(, falseUpdates)(, object))` + +Apply `trueUpdates` if `predicate` is truthy or, if `predicate` is a function, +it evaluates to truthy when called with `object`. Otherwise, apply `falseUpdates`. + +```js +var object = { a: 3 }; +function isEven(x) { return x % 2 === 0; } +function inc(x) { return x + 1; } +function dec(x) { return x - 1; } + +u({ + a: u.if(isEven, inc), +}, object); +// => { a: 2 } +``` + ### `u.map(iteratee(, object))` If iteratee is a function, map it over the values in `object`. diff --git a/lib/if.js b/lib/ifElse.js similarity index 54% rename from lib/if.js rename to lib/ifElse.js index 74a6e46..e4855fe 100644 --- a/lib/if.js +++ b/lib/ifElse.js @@ -1,16 +1,14 @@ import update from './update'; import wrap from './wrap'; -function updateIf(predicate, updates, object) { +function updateIfElse(predicate, trueUpdates, falseUpdates, object) { const test = typeof predicate === 'function' ? predicate(object) : predicate; - if (!test) { - return object; - } + const updates = test ? trueUpdates : falseUpdates; return update(updates, object); } -export default wrap(updateIf); +export default wrap(updateIfElse); diff --git a/lib/index.js b/lib/index.js index 84a2660..cd7c5a1 100644 --- a/lib/index.js +++ b/lib/index.js @@ -1,15 +1,18 @@ import freeze from './freeze'; import _in from './in'; -import _if from './if'; +import ifElse from './ifElse'; import map from './map'; import omit from './omit'; import reject from './reject'; import withDefault from './withDefault'; import update from './update'; +import { placeholder as _ } from 'lodash/function/curry'; + const u = update; -u.if = _if; +u.if = ifElse(_, _, {}); +u.ifElse = ifElse; u.in = _in; u.freeze = freeze; u.map = map; diff --git a/test/ifElse-spec.js b/test/ifElse-spec.js new file mode 100644 index 0000000..efed4ca --- /dev/null +++ b/test/ifElse-spec.js @@ -0,0 +1,42 @@ +import { expect } from 'chai'; +import u from '../lib'; + +describe('u.ifElse', () => { + it('does updates with the else if the predicate is false', () => { + const object = { a: 0 }; + const result = u.ifElse(false, { b: 1 }, { b: 2 }, object); + expect(result).to.eql({ a: 0, b: 2 }); + }); + + it('updates with the true update if the predicate is true', () => { + const object = { a: 0 }; + const result = u.ifElse(true, { b: 1 }, { b: 4 }, object); + expect(result).to.eql({ a: 0, b: 1 }); + }); + + it('will use the result of a function passed as a predicate', () => { + const object = { a: 0 }; + const aIsThree = x => x.a === 3; + const result = u.ifElse(aIsThree, { b: 1 }, { b: 4 }, object); + + expect(result).to.eql({ a: 0, b: 4 }); + }); + + it('can be partially applied', () => { + const object = { a: 2 }; + const isEven = x => x % 2 === 0; + const inc = x => x + 1; + const dec = x => x - 1; + + const result = u({ + a: u.ifElse(isEven, inc, dec), + }, object); + + expect(result).to.eql({ a: 3 }); + }); + + it('freezes the result', () => { + expect(Object.isFrozen(u.ifElse(true, {}, {}, {}))).to.be.true; + expect(Object.isFrozen(u.ifElse(false, {}, {}, {}))).to.be.true; + }); +});