From cd8e08c6e07433335525e528a0506ca72938ca48 Mon Sep 17 00:00:00 2001 From: Paul Date: Mon, 11 Jul 2011 20:59:26 -0400 Subject: [PATCH 1/7] Added route helpers --- index.js | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 64 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index ef3befe..5ff28ed 100644 --- a/index.js +++ b/index.js @@ -118,6 +118,9 @@ Resource.prototype.map = function(method, path, fn){ route += path; route += '.:format?'; + // add convenience functions + this.createRouteHelper(path, route); + // register the route so we may later remove it (this.routes[method] = this.routes[method] || {})[route] = { method: method @@ -125,7 +128,7 @@ Resource.prototype.map = function(method, path, fn){ , orig: orig , fn: fn }; - + // apply the route this.app[method](route, function(req, res, next){ req.format = req.params.format || self.format; @@ -142,7 +145,7 @@ Resource.prototype.map = function(method, path, fn){ fn(req, res, next); } }); - + return this; }; @@ -173,6 +176,11 @@ Resource.prototype.add = function(resource){ resource.map(route.method, route.orig, route.fn); } } + + // delete previous route helpers + for(var methodName in resource.paths) { + delete resourceAccess.path[methodName]; + } return this; }; @@ -211,6 +219,59 @@ Resource.prototype.mapDefaultAction = function(key, fn){ } }; +/** + * Create URL path generators. + * + * @param {String} orig + * @api private + */ + +Resource.prototype.createRouteHelper = function(mapPath, route) { + resourceAccess.path = resourceAccess.path || {}; + var methodName = this.name || "roots"; + var argCount = 0; + + route = route.replace(/\.:format\?$/, ''); + route = route.replace(/\/null/, ''); // Happens with a nameless top level resource + + // Check to see how many levels deep we are and clean up the route + if(this.base.length > 1) { + // build up in reverse + var params = this.base.match(/:(\w+)/g); + params.reverse().forEach(function(param) { + if(param === ':id') { param = ':root'; } + methodName = param.slice(1) + '_' + methodName; + argCount += 1; + }); + } + + if(mapPath === 'new') { + methodName = 'new_' + en.singularize(methodName); + } else if(mapPath.indexOf(this.param) !== (-1)) { + var actionName = mapPath.slice(this.param.length); + if (actionName[0] == '/') { actionName = actionName.slice(1); } + + methodName = en.singularize(methodName); + if(actionName.length > 0) { + methodName = actionName + '_' + methodName; + } + argCount++; + } + + // Add paths to this resource so we can remove them later if we become nested (see #add) + this.paths = this.paths || []; + this.paths.push(methodName); + + // Add to the app.resource object + resourceAccess.path[methodName] = resourceAccess.path[methodName] || function() { + Array.prototype.forEach.call(arguments, function(arg) { + route = route.replace(/:\w+/, arg['id']); + }); + return route; + }; +} + + /** * Setup http verb methods. */ @@ -233,6 +294,7 @@ express.router.methods.concat(['del', 'all']).forEach(function(method){ * @api public */ +var resourceAccess = express.HTTPServer.prototype.resource = express.HTTPSServer.prototype.resource = function(name, actions, opts){ var options = actions || {}; From 544123a1659c1dd4f06dd87c04f57f916cd6abfa Mon Sep 17 00:00:00 2001 From: Paul Date: Mon, 11 Jul 2011 21:06:25 -0400 Subject: [PATCH 2/7] Test resources missed on first pass --- test/resource.path.test.js | 90 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 test/resource.path.test.js diff --git a/test/resource.path.test.js b/test/resource.path.test.js new file mode 100644 index 0000000..db46ad1 --- /dev/null +++ b/test/resource.path.test.js @@ -0,0 +1,90 @@ + +/** + * Module dependencies. + */ +var assert = require('assert') + , express = require('express') + , should = require('should') + , Resource = require('../'); + +module.exports = { + 'test resource': function(){ + var app = express.createServer(); + var ret = app.resource('forums', require('./fixtures/forum')); + + assert.strictEqual(app.resource.path.forums(), '/forums'); + assert.strictEqual(app.resource.path.new_forum(), '/forums/new'); + assert.strictEqual(app.resource.path.forum({id: 5}), '/forums/5'); + assert.strictEqual(app.resource.path.edit_forum({id: 5}), '/forums/5/edit'); + }, + 'test shallow nesting': function(){ + var app = express.createServer(); + + var forumObj = {id: 5}; + var threadObj = {id: 50}; + + var forum = app.resource('forums', require('./fixtures/forum')); + var thread = app.resource('threads', require('./fixtures/thread')); + forum.map(thread); + + assert.strictEqual(app.resource.path.forums(), '/forums'); + assert.strictEqual(app.resource.path.new_forum(), '/forums/new'); + assert.strictEqual(app.resource.path.forum(forumObj), '/forums/5'); + assert.strictEqual(app.resource.path.edit_forum(forumObj), '/forums/5/edit'); + + assert.strictEqual(app.resource.path.forum_threads(forumObj), '/forums/5/threads'); + assert.strictEqual(app.resource.path.new_forum_thread(forumObj), '/forums/5/threads/new'); + assert.strictEqual(app.resource.path.forum_thread(forumObj, threadObj), '/forums/5/threads/50'); + assert.strictEqual(app.resource.path.edit_forum_thread(forumObj, threadObj), '/forums/5/threads/50/edit'); + }, + 'test top level resource nesting': function(){ + var app = express.createServer(); + + var forumObj = {id: 5}; + var threadObj = {id: 50}; + + var forum = app.resource(require('./fixtures/forum')); + var thread = app.resource('threads', require('./fixtures/thread')); + forum.map(thread); + + assert.strictEqual(app.resource.path.roots(), '/'); + assert.strictEqual(app.resource.path.new_root(), '/new'); + assert.strictEqual(app.resource.path.root(forumObj), '/5'); + assert.strictEqual(app.resource.path.edit_root(forumObj), '/5/edit'); + + assert.strictEqual(app.resource.path.root_threads(forumObj), '/5/threads'); + assert.strictEqual(app.resource.path.new_root_thread(forumObj), '/5/threads/new'); + assert.strictEqual(app.resource.path.root_thread(forumObj, threadObj), '/5/threads/50'); + assert.strictEqual(app.resource.path.edit_root_thread(forumObj, threadObj), '/5/threads/50/edit'); + }, + 'test deep resource nesting': function(){ + var app = express.createServer(); + + var userObj = {id: 1}; + var forumObj = {id: 5}; + var threadObj = {id: 50}; + + var user = app.resource('users', { index: function(req, res){ res.end('users'); } }); + var forum = app.resource('forums', require('./fixtures/forum')); + var thread = app.resource('threads', require('./fixtures/thread')); + + var ret = user.add(forum); + ret.should.equal(user); + + var ret = forum.add(thread); + ret.should.equal(forum); + + assert.strictEqual(app.resource.path.users(), '/users'); + + assert.strictEqual(app.resource.path.user_forums(userObj), '/users/1/forums'); + assert.strictEqual(app.resource.path.new_user_forum(userObj), '/users/1/forums/new'); + assert.strictEqual(app.resource.path.user_forum(userObj, forumObj), '/users/1/forums/5'); + assert.strictEqual(app.resource.path.edit_user_forum(userObj, forumObj), '/users/1/forums/5/edit'); + + assert.strictEqual(app.resource.path.user_forum_threads(userObj, forumObj), '/users/1/forums/5/threads'); + assert.strictEqual(app.resource.path.new_user_forum_thread(userObj, forumObj), '/users/1/forums/5/threads/new'); + assert.strictEqual(app.resource.path.user_forum_thread(userObj, forumObj, threadObj), '/users/1/forums/5/threads/50'); + assert.strictEqual(app.resource.path.edit_user_forum_thread(userObj, forumObj, threadObj), '/users/1/forums/5/threads/50/edit'); + }, + +}; \ No newline at end of file From b21decd1f00454eed50ebc677ba4b5afed368385 Mon Sep 17 00:00:00 2001 From: Paul Date: Tue, 12 Jul 2011 09:48:31 -0400 Subject: [PATCH 3/7] Fixed glaring variable scope problem --- index.js | 5 +++-- test/resource.path.test.js | 5 ++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/index.js b/index.js index 5ff28ed..33dd34f 100644 --- a/index.js +++ b/index.js @@ -264,10 +264,11 @@ Resource.prototype.createRouteHelper = function(mapPath, route) { // Add to the app.resource object resourceAccess.path[methodName] = resourceAccess.path[methodName] || function() { + var localRoute = route; Array.prototype.forEach.call(arguments, function(arg) { - route = route.replace(/:\w+/, arg['id']); + localRoute = localRoute.replace(/:\w+/, arg['id']); }); - return route; + return localRoute; }; } diff --git a/test/resource.path.test.js b/test/resource.path.test.js index db46ad1..22385eb 100644 --- a/test/resource.path.test.js +++ b/test/resource.path.test.js @@ -15,8 +15,11 @@ module.exports = { assert.strictEqual(app.resource.path.forums(), '/forums'); assert.strictEqual(app.resource.path.new_forum(), '/forums/new'); assert.strictEqual(app.resource.path.forum({id: 5}), '/forums/5'); + + assert.strictEqual(app.resource.path.forum({id: 10}), '/forums/10'); + assert.strictEqual(app.resource.path.edit_forum({id: 5}), '/forums/5/edit'); - }, + }, 'test shallow nesting': function(){ var app = express.createServer(); From 3fb30d2de6f7e23fd26822d726a41494a4f69d83 Mon Sep 17 00:00:00 2001 From: Paul Date: Tue, 12 Jul 2011 09:57:18 -0400 Subject: [PATCH 4/7] Added custom ID field configuration --- index.js | 4 +++- test/resource.path.test.js | 11 +++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index 33dd34f..f201ee6 100644 --- a/index.js +++ b/index.js @@ -228,6 +228,8 @@ Resource.prototype.mapDefaultAction = function(key, fn){ Resource.prototype.createRouteHelper = function(mapPath, route) { resourceAccess.path = resourceAccess.path || {}; + resourceAccess.path.idField = resourceAccess.path.idField || 'id'; + var methodName = this.name || "roots"; var argCount = 0; @@ -266,7 +268,7 @@ Resource.prototype.createRouteHelper = function(mapPath, route) { resourceAccess.path[methodName] = resourceAccess.path[methodName] || function() { var localRoute = route; Array.prototype.forEach.call(arguments, function(arg) { - localRoute = localRoute.replace(/:\w+/, arg['id']); + localRoute = localRoute.replace(/:\w+/, arg[resourceAccess.path.idField]); }); return localRoute; }; diff --git a/test/resource.path.test.js b/test/resource.path.test.js index 22385eb..1eb68fa 100644 --- a/test/resource.path.test.js +++ b/test/resource.path.test.js @@ -89,5 +89,16 @@ module.exports = { assert.strictEqual(app.resource.path.user_forum_thread(userObj, forumObj, threadObj), '/users/1/forums/5/threads/50'); assert.strictEqual(app.resource.path.edit_user_forum_thread(userObj, forumObj, threadObj), '/users/1/forums/5/threads/50/edit'); }, + 'test resource with custom id field': function(){ + var app = express.createServer(); + var ret = app.resource('forums', require('./fixtures/forum')); + + // NOTE: because this is set across all resources, this test should be run last or it will need + // to be reset for each test. If this is too confusing, we could change to set in on a per-resource basis. + app.resource.path.idField = '_id'; + + assert.strictEqual(app.resource.path.forum({_id: 5}), '/forums/5'); + assert.strictEqual(app.resource.path.edit_forum({_id: 5}), '/forums/5/edit'); + }, }; \ No newline at end of file From f634412a0735f246eb05764219582bf04d5a86cd Mon Sep 17 00:00:00 2001 From: Paul Date: Tue, 12 Jul 2011 11:25:13 -0400 Subject: [PATCH 5/7] Added helper for custom collection actions --- index.js | 5 ++++- test/resource.path.test.js | 19 +++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index f201ee6..00d555e 100644 --- a/index.js +++ b/index.js @@ -258,12 +258,15 @@ Resource.prototype.createRouteHelper = function(mapPath, route) { methodName = actionName + '_' + methodName; } argCount++; + } else if (mapPath.length > 0) { + // custom collection action + methodName = mapPath + '_' + methodName; } // Add paths to this resource so we can remove them later if we become nested (see #add) this.paths = this.paths || []; this.paths.push(methodName); - + // Add to the app.resource object resourceAccess.path[methodName] = resourceAccess.path[methodName] || function() { var localRoute = route; diff --git a/test/resource.path.test.js b/test/resource.path.test.js index 1eb68fa..1fa0058 100644 --- a/test/resource.path.test.js +++ b/test/resource.path.test.js @@ -89,6 +89,25 @@ module.exports = { assert.strictEqual(app.resource.path.user_forum_thread(userObj, forumObj, threadObj), '/users/1/forums/5/threads/50'); assert.strictEqual(app.resource.path.edit_user_forum_thread(userObj, forumObj, threadObj), '/users/1/forums/5/threads/50/edit'); }, + 'test resource with custom actions': function(){ + var app = express.createServer(); + var ret = app.resource('forums', require('./fixtures/forum')); + + var actions = { + lock: function(req, res){ + res.end('login'); + }, + design: function(req, res){ + res.end('logout'); + } + }; + + ret.map('get', 'lock', actions.lock); + ret.map('get', '/design', actions.design); + + assert.strictEqual(app.resource.path.design_forums(), '/forums/design'); + assert.strictEqual(app.resource.path.lock_forum({id: 5}), '/forums/5/lock'); + }, 'test resource with custom id field': function(){ var app = express.createServer(); var ret = app.resource('forums', require('./fixtures/forum')); From a979049fca8942b068db500733101202bfee1bc3 Mon Sep 17 00:00:00 2001 From: Paul Date: Tue, 12 Jul 2011 11:33:16 -0400 Subject: [PATCH 6/7] Helper functions now include _path at the end for consistency with dynamic view helpers --- index.js | 2 +- test/resource.path.test.js | 68 +++++++++++++++++++------------------- 2 files changed, 35 insertions(+), 35 deletions(-) diff --git a/index.js b/index.js index 00d555e..5cbf25b 100644 --- a/index.js +++ b/index.js @@ -268,7 +268,7 @@ Resource.prototype.createRouteHelper = function(mapPath, route) { this.paths.push(methodName); // Add to the app.resource object - resourceAccess.path[methodName] = resourceAccess.path[methodName] || function() { + resourceAccess.path[methodName + '_path'] = resourceAccess.path[methodName] || function() { var localRoute = route; Array.prototype.forEach.call(arguments, function(arg) { localRoute = localRoute.replace(/:\w+/, arg[resourceAccess.path.idField]); diff --git a/test/resource.path.test.js b/test/resource.path.test.js index 1fa0058..17a8a00 100644 --- a/test/resource.path.test.js +++ b/test/resource.path.test.js @@ -12,13 +12,13 @@ module.exports = { var app = express.createServer(); var ret = app.resource('forums', require('./fixtures/forum')); - assert.strictEqual(app.resource.path.forums(), '/forums'); - assert.strictEqual(app.resource.path.new_forum(), '/forums/new'); - assert.strictEqual(app.resource.path.forum({id: 5}), '/forums/5'); + assert.strictEqual(app.resource.path.forums_path(), '/forums'); + assert.strictEqual(app.resource.path.new_forum_path(), '/forums/new'); + assert.strictEqual(app.resource.path.forum_path({id: 5}), '/forums/5'); - assert.strictEqual(app.resource.path.forum({id: 10}), '/forums/10'); + assert.strictEqual(app.resource.path.forum_path({id: 10}), '/forums/10'); - assert.strictEqual(app.resource.path.edit_forum({id: 5}), '/forums/5/edit'); + assert.strictEqual(app.resource.path.edit_forum_path({id: 5}), '/forums/5/edit'); }, 'test shallow nesting': function(){ var app = express.createServer(); @@ -30,15 +30,15 @@ module.exports = { var thread = app.resource('threads', require('./fixtures/thread')); forum.map(thread); - assert.strictEqual(app.resource.path.forums(), '/forums'); - assert.strictEqual(app.resource.path.new_forum(), '/forums/new'); - assert.strictEqual(app.resource.path.forum(forumObj), '/forums/5'); - assert.strictEqual(app.resource.path.edit_forum(forumObj), '/forums/5/edit'); + assert.strictEqual(app.resource.path.forums_path(), '/forums'); + assert.strictEqual(app.resource.path.new_forum_path(), '/forums/new'); + assert.strictEqual(app.resource.path.forum_path(forumObj), '/forums/5'); + assert.strictEqual(app.resource.path.edit_forum_path(forumObj), '/forums/5/edit'); - assert.strictEqual(app.resource.path.forum_threads(forumObj), '/forums/5/threads'); - assert.strictEqual(app.resource.path.new_forum_thread(forumObj), '/forums/5/threads/new'); - assert.strictEqual(app.resource.path.forum_thread(forumObj, threadObj), '/forums/5/threads/50'); - assert.strictEqual(app.resource.path.edit_forum_thread(forumObj, threadObj), '/forums/5/threads/50/edit'); + assert.strictEqual(app.resource.path.forum_threads_path(forumObj), '/forums/5/threads'); + assert.strictEqual(app.resource.path.new_forum_thread_path(forumObj), '/forums/5/threads/new'); + assert.strictEqual(app.resource.path.forum_thread_path(forumObj, threadObj), '/forums/5/threads/50'); + assert.strictEqual(app.resource.path.edit_forum_thread_path(forumObj, threadObj), '/forums/5/threads/50/edit'); }, 'test top level resource nesting': function(){ var app = express.createServer(); @@ -50,15 +50,15 @@ module.exports = { var thread = app.resource('threads', require('./fixtures/thread')); forum.map(thread); - assert.strictEqual(app.resource.path.roots(), '/'); - assert.strictEqual(app.resource.path.new_root(), '/new'); - assert.strictEqual(app.resource.path.root(forumObj), '/5'); - assert.strictEqual(app.resource.path.edit_root(forumObj), '/5/edit'); + assert.strictEqual(app.resource.path.roots_path(), '/'); + assert.strictEqual(app.resource.path.new_root_path(), '/new'); + assert.strictEqual(app.resource.path.root_path(forumObj), '/5'); + assert.strictEqual(app.resource.path.edit_root_path(forumObj), '/5/edit'); - assert.strictEqual(app.resource.path.root_threads(forumObj), '/5/threads'); - assert.strictEqual(app.resource.path.new_root_thread(forumObj), '/5/threads/new'); - assert.strictEqual(app.resource.path.root_thread(forumObj, threadObj), '/5/threads/50'); - assert.strictEqual(app.resource.path.edit_root_thread(forumObj, threadObj), '/5/threads/50/edit'); + assert.strictEqual(app.resource.path.root_threads_path(forumObj), '/5/threads'); + assert.strictEqual(app.resource.path.new_root_thread_path(forumObj), '/5/threads/new'); + assert.strictEqual(app.resource.path.root_thread_path(forumObj, threadObj), '/5/threads/50'); + assert.strictEqual(app.resource.path.edit_root_thread_path(forumObj, threadObj), '/5/threads/50/edit'); }, 'test deep resource nesting': function(){ var app = express.createServer(); @@ -77,17 +77,17 @@ module.exports = { var ret = forum.add(thread); ret.should.equal(forum); - assert.strictEqual(app.resource.path.users(), '/users'); + assert.strictEqual(app.resource.path.users_path(), '/users'); - assert.strictEqual(app.resource.path.user_forums(userObj), '/users/1/forums'); - assert.strictEqual(app.resource.path.new_user_forum(userObj), '/users/1/forums/new'); - assert.strictEqual(app.resource.path.user_forum(userObj, forumObj), '/users/1/forums/5'); - assert.strictEqual(app.resource.path.edit_user_forum(userObj, forumObj), '/users/1/forums/5/edit'); + assert.strictEqual(app.resource.path.user_forums_path(userObj), '/users/1/forums'); + assert.strictEqual(app.resource.path.new_user_forum_path(userObj), '/users/1/forums/new'); + assert.strictEqual(app.resource.path.user_forum_path(userObj, forumObj), '/users/1/forums/5'); + assert.strictEqual(app.resource.path.edit_user_forum_path(userObj, forumObj), '/users/1/forums/5/edit'); - assert.strictEqual(app.resource.path.user_forum_threads(userObj, forumObj), '/users/1/forums/5/threads'); - assert.strictEqual(app.resource.path.new_user_forum_thread(userObj, forumObj), '/users/1/forums/5/threads/new'); - assert.strictEqual(app.resource.path.user_forum_thread(userObj, forumObj, threadObj), '/users/1/forums/5/threads/50'); - assert.strictEqual(app.resource.path.edit_user_forum_thread(userObj, forumObj, threadObj), '/users/1/forums/5/threads/50/edit'); + assert.strictEqual(app.resource.path.user_forum_threads_path(userObj, forumObj), '/users/1/forums/5/threads'); + assert.strictEqual(app.resource.path.new_user_forum_thread_path(userObj, forumObj), '/users/1/forums/5/threads/new'); + assert.strictEqual(app.resource.path.user_forum_thread_path(userObj, forumObj, threadObj), '/users/1/forums/5/threads/50'); + assert.strictEqual(app.resource.path.edit_user_forum_thread_path(userObj, forumObj, threadObj), '/users/1/forums/5/threads/50/edit'); }, 'test resource with custom actions': function(){ var app = express.createServer(); @@ -105,8 +105,8 @@ module.exports = { ret.map('get', 'lock', actions.lock); ret.map('get', '/design', actions.design); - assert.strictEqual(app.resource.path.design_forums(), '/forums/design'); - assert.strictEqual(app.resource.path.lock_forum({id: 5}), '/forums/5/lock'); + assert.strictEqual(app.resource.path.design_forums_path(), '/forums/design'); + assert.strictEqual(app.resource.path.lock_forum_path({id: 5}), '/forums/5/lock'); }, 'test resource with custom id field': function(){ var app = express.createServer(); @@ -116,8 +116,8 @@ module.exports = { // to be reset for each test. If this is too confusing, we could change to set in on a per-resource basis. app.resource.path.idField = '_id'; - assert.strictEqual(app.resource.path.forum({_id: 5}), '/forums/5'); - assert.strictEqual(app.resource.path.edit_forum({_id: 5}), '/forums/5/edit'); + assert.strictEqual(app.resource.path.forum_path({_id: 5}), '/forums/5'); + assert.strictEqual(app.resource.path.edit_forum_path({_id: 5}), '/forums/5/edit'); }, }; \ No newline at end of file From b4e69aa17c409b1b3df2b3507662f04f527310ec Mon Sep 17 00:00:00 2001 From: Paul Covell Date: Wed, 27 Jul 2011 16:02:48 -0400 Subject: [PATCH 7/7] Use object if object[idField] is undefined for path ID. Per discussion on Issue #20. --- index.js | 3 ++- test/resource.path.test.js | 10 ++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index 5cbf25b..0dd2b29 100644 --- a/index.js +++ b/index.js @@ -271,7 +271,8 @@ Resource.prototype.createRouteHelper = function(mapPath, route) { resourceAccess.path[methodName + '_path'] = resourceAccess.path[methodName] || function() { var localRoute = route; Array.prototype.forEach.call(arguments, function(arg) { - localRoute = localRoute.replace(/:\w+/, arg[resourceAccess.path.idField]); + var id = arg[resourceAccess.path.idField] || arg; + localRoute = localRoute.replace(/:\w+/, id); }); return localRoute; }; diff --git a/test/resource.path.test.js b/test/resource.path.test.js index 17a8a00..2f17a4f 100644 --- a/test/resource.path.test.js +++ b/test/resource.path.test.js @@ -108,6 +108,16 @@ module.exports = { assert.strictEqual(app.resource.path.design_forums_path(), '/forums/design'); assert.strictEqual(app.resource.path.lock_forum_path({id: 5}), '/forums/5/lock'); }, + 'test resource with direct id value': function(){ + var app = express.createServer(); + var ret = app.resource('forums', require('./fixtures/forum')); + + assert.strictEqual(app.resource.path.forum_path(5), '/forums/5'); + assert.strictEqual(app.resource.path.edit_forum_path(5), '/forums/5/edit'); + + assert.strictEqual(app.resource.path.forum_path("5"), '/forums/5'); + assert.strictEqual(app.resource.path.edit_forum_path("5"), '/forums/5/edit'); + }, 'test resource with custom id field': function(){ var app = express.createServer(); var ret = app.resource('forums', require('./fixtures/forum'));