1
0
Fork 0

Merge pull request #911 from pluma/foxx-controller-di

Foxx Controller dependency injection
This commit is contained in:
Lucas Dohmen 2014-06-18 12:55:23 +02:00
commit d9e88ce5bb
3 changed files with 154 additions and 3 deletions

View File

@ -87,6 +87,8 @@ Controller = function (context, options) {
urlPrefix = context.prefix + "/" + urlPrefix;
}
this.injected = Object.create(null);
this.injectors = Object.create(null);
this.routingInfo.urlPrefix = urlPrefix;
this.collectionPrefix = context.collectionPrefix;
@ -133,6 +135,14 @@ extend(Controller.prototype, {
return this.applicationContext.collection(name);
},
addInjector: function(name, factory) {
if (factory === undefined) {
_.extend(this.injectors, name);
} else {
this.injectors[name] = factory;
}
},
////////////////////////////////////////////////////////////////////////////////
/// @fn JSF_foxx_controller_handleRequest
/// @brief Handle a request
@ -147,7 +157,7 @@ extend(Controller.prototype, {
handleRequest: function (method, route, callback) {
'use strict';
var newRoute = internal.constructRoute(method, route, callback),
var newRoute = internal.constructRoute(method, route, callback, this),
requestContext = new RequestContext(this.allRoutes, this.models, newRoute, this.rootElement),
summary;

View File

@ -84,12 +84,23 @@ constructNickname = function (httpMethod, url) {
.toLowerCase();
};
constructRoute = function (method, route, callback) {
constructRoute = function (method, route, callback, controller) {
'use strict';
return {
url: constructUrlObject(route, undefined, method),
action: {
callback: callback
callback: function(req, res) {
Object.keys(controller.injectors).forEach(function(key) {
if (Object.prototype.hasOwnProperty.call(controller.injected, key)) return;
var injector = controller.injectors[key];
if (typeof injector === 'function') {
controller.injected[key] = injector();
} else {
controller.injected[key] = injector;
}
});
callback(req, res, controller.injected);
}
},
docs: {
parameters: [],

View File

@ -245,6 +245,135 @@ function SetRoutesFoxxControllerSpec () {
};
}
function ControllerInjectionSpec () {
var app, routes, models;
return {
testInjectFactoryFunction: function () {
var app = new FoxxController(fakeContext),
req = {},
res = {},
timesCalled = 0;
app.addInjector({thing: function() {timesCalled++;}});
app.get('/foxx', function () {});
app.routingInfo.routes[0].action.callback(req, res);
app.routingInfo.routes[0].action.callback(req, res);
assertEqual(timesCalled, 1);
},
testInjectNameValue: function () {
var app = new FoxxController(fakeContext),
req = {},
res = {},
timesCalled = 0;
app.addInjector('thing', function() {timesCalled++;});
app.get('/foxx', function () {});
app.routingInfo.routes[0].action.callback(req, res);
app.routingInfo.routes[0].action.callback(req, res);
assertEqual(timesCalled, 1);
},
testInjectOverwrite: function () {
var app = new FoxxController(fakeContext),
req = {},
res = {},
wrongFuncCalled = false,
timesCalled = 0;
app.addInjector({thing: function() {wrongFuncCalled = true;}});
app.addInjector({thing: function() {timesCalled++;}});
app.get('/foxx', function () {});
app.routingInfo.routes[0].action.callback(req, res);
app.routingInfo.routes[0].action.callback(req, res);
assertFalse(wrongFuncCalled);
assertEqual(timesCalled, 1);
},
testInjectInRoute: function () {
var app = new FoxxController(fakeContext),
req = {},
res = {},
calledA = false,
calledB = false,
calledC = false;
app.addInjector({thing: function() {calledA = true;}});
app.get('/foxx', function () {
app.addInjector({
thing: function() {calledB = true;},
other: function() {calledC = true;}
});
});
app.routingInfo.routes[0].action.callback(req, res);
app.routingInfo.routes[0].action.callback(req, res);
app.routingInfo.routes[0].action.callback(req, res);
assertTrue(calledA);
assertFalse(calledB);
assertTrue(calledC);
},
testInjectResultPassedThrough: function () {
var app = new FoxxController(fakeContext),
req = {},
res = {},
called = false;
app.addInjector({thing: function() {return 'value';}});
app.get('/foxx', function (req, res, injected) {
assertEqual(injected.thing, 'value');
called = true;
});
app.routingInfo.routes[0].action.callback(req, res);
assertTrue(called);
},
testInjectSimpleValues: function () {
var app = new FoxxController(fakeContext),
req = {},
res = {},
called = false;
var injectors = {
obj: {a: 0, b: 1},
arr: ['one', 'two'],
str: 'hello',
num: 42
};
app.addInjector(injectors);
app.get('/foxx', function (req, res, injected) {
assertEqual(typeof injected.obj, 'object');
assertEqual(typeof injected.arr, 'object');
assertEqual(typeof injected.str, 'string');
assertEqual(typeof injected.num, 'number');
assertTrue(Array.isArray(injected.arr));
assertEqual(injected.obj, injectors.obj);
assertEqual(injected.arr, injectors.arr);
assertEqual(injected.str, injectors.str);
assertEqual(injected.num, injectors.num);
called = true;
});
app.routingInfo.routes[0].action.callback(req, res);
assertTrue(called);
}
};
}
function DocumentationAndConstraintsSpec () {
var app, routes, models;
@ -872,6 +1001,7 @@ function FoxxControllerWithRootElement () {
jsunity.run(CreateFoxxControllerSpec);
jsunity.run(SetRoutesFoxxControllerSpec);
jsunity.run(ControllerInjectionSpec);
jsunity.run(DocumentationAndConstraintsSpec);
jsunity.run(AddMiddlewareFoxxControllerSpec);
jsunity.run(CommentDrivenDocumentationSpec);