Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Standardize prop or and path or functionality to match documentation #2995

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 5 additions & 1 deletion source/path.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ import paths from './paths';
*/

var path = _curry2(function path(pathAr, obj) {
return paths([pathAr], obj)[0];
try {
return paths([pathAr], obj)[0];
} catch (e) {
return undefined;
}
});
export default path;
10 changes: 6 additions & 4 deletions source/pathOr.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import _curry3 from './internal/_curry3';
import defaultTo from './defaultTo';
import path from './path';

import paths from './paths';

/**
* If the given, non-null object has a value at the given path, returns the
Expand All @@ -23,6 +21,10 @@ import path from './path';
* R.pathOr('N/A', ['a', 'b'], {c: {b: 2}}); //=> "N/A"
*/
var pathOr = _curry3(function pathOr(d, p, obj) {
return defaultTo(d, path(p, obj));
try {
return paths([p], obj)[0];
} catch (e) {
return d;
}
});
export default pathOr;
26 changes: 24 additions & 2 deletions source/paths.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,33 @@ var paths = _curry2(function paths(pathsArray, obj) {
var p;
while (idx < paths.length) {
if (val == null) {
return;
throw new Error('Specified path not in object2');
}

p = paths[idx];
val = _isInteger(p) ? nth(p, val) : val[p];

if (
_isInteger(p) &&
Array.isArray(val) &&
(
(p < 0 && (val.length >= Math.abs(p))) ||
(p >= 0 && p < val.length)
)
) {
// nth is only intended to be used on arrays.
// Have to check array bounds because nth returns
// undefined when the value is not in the list
// and when the index is out of the range
val = nth(p, val);
} else if (
val instanceof Object &&
p in val) {
val = val[p];
} else {
throw new Error('Specified path not in object');
}
idx += 1;

}
return val;
});
Expand Down
16 changes: 8 additions & 8 deletions source/propOr.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import _curry3 from './internal/_curry3';
import defaultTo from './defaultTo';
import prop from './prop';

import _curry3 from './internal/_curry3'
import defaultTo from './defaultTo'
import prop from './prop'
import pathOr from './pathOr'

/**
* If the given, non-null object has an own property with the specified name,
Expand Down Expand Up @@ -29,7 +29,7 @@ import prop from './prop';
* favorite(alice); //=> undefined
* favoriteWithDefault(alice); //=> 'Ramda'
*/
var propOr = _curry3(function propOr(val, p, obj) {
return defaultTo(val, prop(p, obj));
});
export default propOr;
var propOr = _curry3(function propOr (val, p, obj) {
return pathOr(val, [p], obj)
})
export default propOr
4 changes: 2 additions & 2 deletions test/path.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ describe('path', function() {
eq(R.path(['a', 'b'], {a: null}), undefined);
});

it('works with falsy items', function() {
eq(R.path(['toString'], false), Boolean.prototype.toString);
it('returns undefined for non-object items', function() {
eq(R.path(['toString'], false), undefined);
});

});
4 changes: 2 additions & 2 deletions test/pathOr.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ describe('pathOr', function() {
eq(R.pathOr('Unknown', ['toString'], undefined), 'Unknown');
});

it('works with falsy items', function() {
eq(R.pathOr('Unknown', ['toString'], false), Boolean.prototype.toString);
it('returns the default for non-object items', function() {
eq(R.pathOr('Unknown', ['toString'], false), 'Unknown');
});

});
53 changes: 47 additions & 6 deletions test/paths.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
var assert = require('assert');

var R = require('../source');
var eq = require('./shared/eq');

Expand All @@ -17,27 +19,66 @@ describe('paths', function() {
};
it('takes paths and returns values at those paths', function() {
eq(R.paths([['a', 'b', 'c'], ['x', 'y']], obj), [1, 'Alice']);
eq(R.paths([['a', 'b', 'd'], ['p', 'q']], obj), [2, undefined]);
assert.throws(function() {
R.paths([['a', 'b', 'd'], ['p', 'q']], obj);
}, function(err) {
return (err instanceof Error &&
err.message === 'Specified path not in object');
});
});

it('takes a paths that contains indices into arrays', function() {
eq(R.paths([['p', 0, 'q'], ['x', 'z', 0, 0]], obj), [3, {}]);
eq(R.paths([['p', 0, 'q'], ['x', 'z', 2, 1]], obj), [3, undefined]);
});

it('takes a path that contains negative indices into arrays', function() {
eq(R.paths([['p', -2, 'q'], ['p', -1]], obj), [3, 'Hi']);
eq(R.paths([['p', -4, 'q'], ['x', 'z', -1, 0]], obj), [undefined, {}]);
});

it("gets a deep property's value from objects", function() {
eq(R.paths([['a', 'b']], obj), [obj.a.b]);
eq(R.paths([['p', 0]], obj), [obj.p[0]]);
});

it('returns undefined for items not found', function() {
eq(R.paths([['a', 'x', 'y']], obj), [undefined]);
eq(R.paths([['p', 2]], obj), [undefined]);
it('throws an error for items not found in an object', function() {
assert.throws(function() {
R.paths([['a', 'x', 'y']], obj);
}, function(err) {
return (err instanceof Error &&
err.message === 'Specified path not in object');
});

assert.throws(function() {
R.paths([['p', 0, 'q'], ['x', 'z', 2, 1]], obj);
}, function(err) {
return (err instanceof Error &&
err.message === 'Specified path not in object');
});

assert.throws(function() {
R.paths([['p', -4, 'q'], ['x', 'z', -1, 0]], obj);
}, function(err) {
return (err instanceof Error &&
err.message === 'Specified path not in object');
});
});

it('does not index into strings values', function() {
assert.throws(function() {
R.paths([['x', 'y', 1]], obj);
}, function(err) {
return (err instanceof Error &&
err.message === 'Specified path not in object');
});
});

it('raises an error for items not found in a list', function() {
assert.throws(function() {
eq(R.paths([['p', 2]], obj), [undefined]);
}, function(err) {
return (err instanceof Error &&
err.message === 'Specified path not in object');
});
});

});
6 changes: 3 additions & 3 deletions test/propOr.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ describe('propOr', function() {
eq(nm(void 0), 'Unknown');
});

it('uses the default when supplied an object with a nil value', function() {
eq(R.propOr('foo', 'x', {x: null}), 'foo');
eq(R.propOr('foo', 'x', {x: undefined}), 'foo');
it('returns the value when supplied an object with a nil value', function() {
eq(R.propOr('foo', 'x', {x: null}), null);
eq(R.propOr('foo', 'x', {x: undefined}), undefined);
});

it('handles number as property', function() {
Expand Down