Skip to content

Commit

Permalink
Add ability to pass multiple named param objects
Browse files Browse the repository at this point in the history
  • Loading branch information
rf- committed Apr 6, 2015
1 parent 65dcaee commit 5a46025
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 6 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ userPostUrl({ userId: 1, id: 2 });

// returns '/users/1/posts/2?q=javascript'
userPostUrl(1, 2, { q: 'javascript' });

// returns '/users/1/posts/2?q=javascript&foo=bar'
userPostUrl(1, 2, { q: 'javascript' }, { foo: 'bar' });
```

### Defaults
Expand Down
60 changes: 54 additions & 6 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -137,16 +137,19 @@ function _generateHelper(urlSpec, defaults, encodeQueryString) {
}

return (...args) => {
const lastArg = args[args.length - 1];
const namedParamObjects = [];
let namedParams;

if (lastArg && typeof lastArg === 'object') {
namedParams = lastArg;
args.pop();
} else {
namedParams = {};
for (let i = args.length - 1; i >= 0; i--) {
if (_isSimpleObject(args[i])) {
namedParamObjects.unshift(args.pop());
} else {
break;
}
}

namedParams = _objectAssign({}, ...namedParamObjects);

return _generateUrl(urlSpec, defaults, args, namedParams, encodeQueryString);
};
}
Expand Down Expand Up @@ -349,3 +352,48 @@ function _simpleEncodeParams(obj) {

return result.join('&');
}

/**
* @private
* @return {boolean} Is the given object a "simple" object? We use this to
* determine which params to a URL helper should be treated as containing
* key-value pairs of parameters.
*/
function _isSimpleObject(obj) {
return (
Object.prototype.toString.call(obj) === '[object Object]' &&
obj.constructor.prototype.hasOwnProperty('isPrototypeOf')
);
}

/**
* @private
* @license Polyfill for Object.assign from Mozilla Developer Network. Any
* copyright is dedicated to the Public Domain:
* http://creativecommons.org/publicdomain/zero/1.0/
* @return {object} A merged version of the given objects, with later
* parameters having precedence over earlier ones.
*/
function _objectAssign(target) {
if (target === undefined || target === null) {
throw new TypeError('Cannot convert first argument to object');
}

var to = Object(target);
for (var i = 1; i < arguments.length; i++) {
var nextSource = arguments[i];
if (nextSource === undefined || nextSource === null) {
continue;
}

var keysArray = Object.keys(Object(nextSource));
for (var nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex++) {
var nextKey = keysArray[nextIndex];
var desc = Object.getOwnPropertyDescriptor(nextSource, nextKey);
if (desc !== undefined && desc.enumerable) {
to[nextKey] = nextSource[nextKey];
}
}
}
return to;
}
15 changes: 15 additions & 0 deletions spec/generate_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ describe('generate', () => {
.toEqual('/users/1/posts/2?extra_param=3&another_extra_param=4');
});

it('merges multiple named param objects', () => {
expect(userPostUrl(1, { id: 2 }, { je: 3 }))
.toEqual('/users/1/posts/2?je=3');
});

it('leaves a query param out if null is provided', () => {
expect(userPostUrl(1, 2, { extra_param: null }))
.toEqual('/users/1/posts/2');
Expand Down Expand Up @@ -160,5 +165,15 @@ describe('generate', () => {
it('omits the ? if the custom encoder returns an empty string', () => {
expect(homeUrl({ dontReturnHello: true })).toEqual('/');
});

it('merges all objects passed at the end of the param list', () => {
expect(
homeUrl(
{ dontReturnHello: true },
{ returnHello: true },
{ _host: 'example.com' }
)
).toEqual('//example.com/?hello');
});
});
});

0 comments on commit 5a46025

Please sign in to comment.