This commit is contained in:
Aaron Jensen 2015-08-06 20:48:04 -07:00
parent 59ec770a88
commit 5c0855b9df
7 changed files with 118 additions and 8 deletions

View File

@ -1,9 +1,10 @@
# Change Log # Change Log
## [unreleased] ## [unreleased]
* Add `u.is` to test predicates in a single path. (https://github.com/substantial/updeep/issues/13)
## [0.4.0] ## [0.4.0]
* Add `u.if` and `u.ifElse` to conditionally update objects. * Add `u.if` and `u.ifElse` to conditionally update objects. (https://github.com/substantial/updeep/issues/12)
* Add `u.map` to update all values in an array or object. * Add `u.map` to update all values in an array or object.
* Replace object outright if null or constant provided as `updates`. * 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. * Freeze objects returned by helper methods that use `update` like `withDefault`, `map`, `in`, etc. Previously, only `u` did freezing.

View File

@ -219,8 +219,8 @@ u({ x: u.omit(['b', 'c']) }, { x: { a: 0, b: 0, c: 0 } });
Reject items from an array. See [`_.reject`](https://lodash.com/docs#reject). Reject items from an array. See [`_.reject`](https://lodash.com/docs#reject).
```js ```js
function even(i) { return i % 2 === 0 }; function isEven(i) { return i % 2 === 0; }
u({ x: u.reject(even) }, { x: [1, 2, 3, 4] }); u({ x: u.reject(isEven) }, { x: [1, 2, 3, 4] });
// => { x: [1, 3] } // => { x: [1, 3] }
``` ```
@ -235,6 +235,29 @@ u({ x: u.withDefault([], { 0: 3 }) }, {});
See the [tests] for more examples. See the [tests] for more examples.
### `u.is(path(, predicate)(, object))`
Returns `true` if the `predicate` matches the `path` applied to the `object`.
If the `predicate` is a function, the result is returned. If not, they are compared with `===`.
```js
u.is('a.b', 4, { a: { b: 4 } });
// => true
```
```js
function isEven(i) { return i % 2 === 0; }
u.is('a.b', isEven, { a: { b: 4 } });
// => true
```
```js
u({
person: u.if(u.is('name.first', 'Jen'), u.in('name.last', 'Simpson'))
}, { person: { name: { first: 'Jen', last: 'Matthews' } } });
// => { person: { name: { first: 'Jen', last: 'Simpson' } } }
```
## Install ## Install
```sh ```sh

View File

@ -1,12 +1,9 @@
import curry from 'lodash/function/curry'; import curry from 'lodash/function/curry';
import reject from 'lodash/collection/reject';
import update from './update'; import update from './update';
import splitPath from './util/splitPath';
function updateIn(path, value, object) { function updateIn(path, value, object) {
const parts = Array.isArray(path) ? const parts = splitPath(path);
path :
reject(path.split('.'), x => !x);
const updates = parts.reduceRight((acc, key) => ({ [key]: acc }), value); const updates = parts.reduceRight((acc, key) => ({ [key]: acc }), value);
return update(updates, object); return update(updates, object);

View File

@ -1,5 +1,6 @@
import freeze from './freeze'; import freeze from './freeze';
import _in from './in'; import _in from './in';
import is from './is';
import ifElse from './ifElse'; import ifElse from './ifElse';
import map from './map'; import map from './map';
import omit from './omit'; import omit from './omit';
@ -14,6 +15,7 @@ const u = update;
u.if = ifElse(_, _, {}); u.if = ifElse(_, _, {});
u.ifElse = ifElse; u.ifElse = ifElse;
u.in = _in; u.in = _in;
u.is = is;
u.freeze = freeze; u.freeze = freeze;
u.map = map; u.map = map;
u.omit = omit; u.omit = omit;

21
lib/is.js Normal file
View File

@ -0,0 +1,21 @@
import splitPath from './util/splitPath';
import curry from 'lodash/function/curry';
function is(path, predicate, object) {
const parts = splitPath(path);
let rest = object;
let part;
for (part of parts) {
if (typeof rest === 'undefined') return false;
rest = rest[part];
}
if (typeof predicate === 'function') {
return predicate(rest);
}
return predicate === rest;
}
export default curry(is);

7
lib/util/splitPath.js Normal file
View File

@ -0,0 +1,7 @@
import reject from 'lodash/collection/reject';
export default function splitPath(path) {
return Array.isArray(path) ?
path :
reject(path.split('.'), x => !x);
}

59
test/is-spec.js Normal file
View File

@ -0,0 +1,59 @@
import { expect } from 'chai';
import u from '../lib';
describe('u.is', () => {
it('returns true if path matches a value predicate', () => {
const result = u.is('a.b', 4, { a: { b: 4 } });
expect(result).to.be.true;
});
it('returns true if path matches a function predicate', () => {
const isEven = x => x % 2 === 0;
const result = u.is('a.b', isEven, { a: { b: 6 } });
expect(result).to.be.true;
});
it('returns false if path matches a value predicate', () => {
const result = u.is('a.b', 4, { a: { b: 5 } });
expect(result).to.be.false;
});
it('returns false if path matches a function predicate', () => {
const isEven = x => x % 2 === 0;
const result = u.is('a.b', isEven, { a: { b: 7 } });
expect(result).to.be.false;
});
it('returns false if the path does not exist', () => {
const result = u.is('a.b.c.d', 4, { a: { b: {} } });
expect(result).to.be.false;
});
it('can test for undefined', () => {
const result = u.is('a.b.c', undefined, { a: { b: {} } });
expect(result).to.be.true;
});
it('tests the actual object if a blank path is given', () => {
const result = u.is('', 4, 4);
expect(result).to.be.true;
});
it('can use arrays as paths', () => {
const result = u.is(['a', 'b'], 4, { a: { b: 4 } });
expect(result).to.be.true;
});
it('can include array indexes in paths', () => {
let result = u.is('a.1.b', 4, { a: [{}, { b: 4 }] });
expect(result).to.be.true;
result = u.is(['a', 1, 'b'], 4, { a: [{}, { b: 4 }] });
expect(result).to.be.true;
});
it('can be partially applied', () => {
const result = u.is('a.b')(4)({ a: { b: 4 } });
expect(result).to.be.true;
});
});