Skip to content
This repository has been archived by the owner on Apr 12, 2024. It is now read-only.

Commit

Permalink
feat($resource): ability to override url in resource actions
Browse files Browse the repository at this point in the history
Resources now can defined per action url override. The url is treated
as a template rather than a literal string, so fancy interpolations
are possible.

See attached tests for example usage.
  • Loading branch information
nolazybits authored and IgorMinar committed Feb 27, 2013
1 parent cf17c6a commit 60f1f09
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 13 deletions.
30 changes: 17 additions & 13 deletions src/ngResource/resource.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@
* - **`params`** – {Object=} – Optional set of pre-bound parameters for this action. If any of the
* parameter value is a function, it will be executed every time when a param value needs to be
* obtained for a request (unless the param was overriden).
* - **`url`** – {string} – action specific `url` override. The url templating is supported just like
* for the resource-level urls.
* - **`isArray`** – {boolean=} – If true then the returned object for this action is an array, see
* `returns` section.
* - **`transformRequest`** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –
Expand Down Expand Up @@ -306,30 +308,32 @@ angular.module('ngResource', ['ng']).
function Route(template, defaults) {
this.template = template = template + '#';
this.defaults = defaults || {};
var urlParams = this.urlParams = {};
forEach(template.split(/\W/), function(param){
if (param && (new RegExp("(^|[^\\\\]):" + param + "\\W").test(template))) {
urlParams[param] = true;
}
});
this.template = template.replace(/\\:/g, ':');
this.urlParams = {};
}

Route.prototype = {
setUrlParams: function(config, params) {
setUrlParams: function(config, params, actionUrl) {
var self = this,
url = this.template,
url = actionUrl || self.template,
val,
encodedVal;

var urlParams = self.urlParams = {};
forEach(url.split(/\W/), function(param){
if (param && (new RegExp("(^|[^\\\\]):" + param + "(\\W|$)").test(url))) {
urlParams[param] = true;
}
});
url = url.replace(/\\:/g, ':');

params = params || {};
forEach(this.urlParams, function(_, urlParam){
forEach(self.urlParams, function(_, urlParam){
val = params.hasOwnProperty(urlParam) ? params[urlParam] : self.defaults[urlParam];
if (angular.isDefined(val) && val !== null) {
encodedVal = encodeUriSegment(val);
url = url.replace(new RegExp(":" + urlParam + "(\\W)", "g"), encodedVal + "$1");
url = url.replace(new RegExp(":" + urlParam + "(\\W|$)", "g"), encodedVal + "$1");
} else {
url = url.replace(new RegExp("(\/?):" + urlParam + "(\\W)", "g"), function(match,
url = url.replace(new RegExp("(\/?):" + urlParam + "(\\W|$)", "g"), function(match,
leadingSlashes, tail) {
if (tail.charAt(0) == '/') {
return tail;
Expand Down Expand Up @@ -427,7 +431,7 @@ angular.module('ngResource', ['ng']).
}
});
httpConfig.data = data;
route.setUrlParams(httpConfig, extend({}, extractParams(data, action.params || {}), params));
route.setUrlParams(httpConfig, extend({}, extractParams(data, action.params || {}), params), action.url);

function markResolved() { value.$resolved = true; }

Expand Down
62 changes: 62 additions & 0 deletions test/ngResource/resourceSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -703,4 +703,66 @@ describe("resource", function() {
$httpBackend.flush();
expect(person.id).toEqual(456);
});


describe('action-level url override', function() {

it('should support overriding url template with static url', function() {
$httpBackend.expect('GET', '/override-url?type=Customer&typeId=123').respond({id: 'abc'});
var TypeItem = $resource('/:type/:typeId', {type: 'Order'}, {
get: {
method: 'GET',
params: {type: 'Customer'},
url: '/override-url'
}
});
var item = TypeItem.get({typeId: 123});
$httpBackend.flush();
expect(item).toEqualData({id: 'abc'});
});


it('should support overriding url template with a new template ending in param', function() {
// url parameter in action, parameter ending the string
$httpBackend.expect('GET', '/Customer/123').respond({id: 'abc'});
var TypeItem = $resource('/foo/:type', {type: 'Order'}, {
get: {
method: 'GET',
params: {type: 'Customer'},
url: '/:type/:typeId'
}
});
var item = TypeItem.get({typeId: 123});
$httpBackend.flush();
expect(item).toEqualData({id: 'abc'});

// url parameter in action, parameter not ending the string
$httpBackend.expect('GET', '/Customer/123/pay').respond({id: 'abc'});
var TypeItem = $resource('/foo/:type', {type: 'Order'}, {
get: {
method: 'GET',
params: {type: 'Customer'},
url: '/:type/:typeId/pay'
}
});
var item = TypeItem.get({typeId: 123});
$httpBackend.flush();
expect(item).toEqualData({id: 'abc'});
});


it('should support overriding url template with a new template ending in string', function() {
$httpBackend.expect('GET', '/Customer/123/pay').respond({id: 'abc'});
var TypeItem = $resource('/foo/:type', {type: 'Order'}, {
get: {
method: 'GET',
params: {type: 'Customer'},
url: '/:type/:typeId/pay'
}
});
var item = TypeItem.get({typeId: 123});
$httpBackend.flush();
expect(item).toEqualData({id: 'abc'});
});
});
});

4 comments on commit 60f1f09

@evictor
Copy link

@evictor evictor commented on 60f1f09 May 1, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this... Needed this for a while.

@evictor
Copy link

@evictor evictor commented on 60f1f09 May 1, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any idea when this will be released?

@pkozlowski-opensource
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@evictor - it was already released in 1.1.4

@evictor
Copy link

@evictor evictor commented on 60f1f09 May 1, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My bad, was looking at 1.0.6. Thanks again!

Please sign in to comment.