@@ -40,6 +40,9 @@ type Controller struct {
40
40
Validation * Validation // Data validation helpers
41
41
}
42
42
43
+ // The map of controllers, controllers are mapped by using the namespace|controller_name as the key
44
+ var controllers = make (map [string ]* ControllerType )
45
+
43
46
// NewController returns new controller instance for Request and Response
44
47
func NewController (req * Request , resp * Response ) * Controller {
45
48
return & Controller {
@@ -91,10 +94,19 @@ func (c *Controller) setStatusIfNil(status int) {
91
94
//
92
95
// This action will render views/Users/ShowUser.html, passing in an extra
93
96
// key-value "user": (User).
97
+ //
98
+ // This is the slower magical version which uses the runtime
99
+ // to determine
100
+ // 1) Set c.ViewArgs to the arguments passed into this function
101
+ // 2) How to call the RenderTemplate by building the following line
102
+ // c.RenderTemplate(c.Name + "/" + c.MethodType.Name + "." + c.Request.Format)
103
+ //
104
+ // If you want your code to run faster it is recommended you add the template values directly
105
+ // to the c.ViewArgs and call c.RenderTemplate directly
94
106
func (c * Controller ) Render (extraViewArgs ... interface {}) Result {
95
107
c .setStatusIfNil (http .StatusOK )
96
108
97
- // Get the calling function name .
109
+ // Get the calling function line number .
98
110
_ , _ , line , ok := runtime .Caller (1 )
99
111
if ! ok {
100
112
ERROR .Println ("Failed to get Caller information" )
@@ -131,7 +143,7 @@ func (c *Controller) RenderTemplate(templatePath string) Result {
131
143
}
132
144
133
145
return & RenderTemplateResult {
134
- Template : template ,
146
+ Template : template ,
135
147
ViewArgs : c .ViewArgs ,
136
148
}
137
149
}
@@ -276,11 +288,21 @@ func (c *Controller) Message(message string, args ...interface{}) (value string)
276
288
// It sets the following properties: Name, Action, Type, MethodType
277
289
func (c * Controller ) SetAction (controllerName , methodName string ) error {
278
290
291
+ return c .SetTypeAction (controllerName , methodName , nil )
292
+ }
293
+ // SetAction sets the assigns the Controller type, sets the action and initializes the controller
294
+ func (c * Controller ) SetTypeAction (controllerName , methodName string , typeOfController * ControllerType ) error {
295
+
279
296
// Look up the controller and method types.
280
- var ok bool
281
- if c .Type , ok = controllers [strings .ToLower (controllerName )]; ! ok {
282
- return errors .New ("revel/controller: failed to find controller " + controllerName )
297
+ if typeOfController == nil {
298
+ if c .Type = ControllerTypeByName (controllerName , anyModule ); c .Type == nil {
299
+ return errors .New ("revel/controller: failed to find controller " + controllerName )
300
+ }
301
+ } else {
302
+ c .Type = typeOfController
283
303
}
304
+
305
+ // Note method name is case insensitive search
284
306
if c .MethodType = c .Type .Method (methodName ); c .MethodType == nil {
285
307
return errors .New ("revel/controller: failed to find action " + methodName )
286
308
}
@@ -294,6 +316,27 @@ func (c *Controller) SetAction(controllerName, methodName string) error {
294
316
return nil
295
317
}
296
318
319
+ func ControllerTypeByName (controllerName string , moduleSource * Module ) (c * ControllerType ) {
320
+ var found bool
321
+ if c , found = controllers [controllerName ]; ! found {
322
+ // Backup, passed in controllerName should be in lower case, but may not be
323
+ if c , found = controllers [strings .ToLower (controllerName )]; ! found {
324
+ INFO .Printf ("Cannot find controller name '%s' in controllers map " , controllerName )
325
+ // Search for the controller by name
326
+ for _ , cType := range controllers {
327
+ testControllerName := strings .ToLower (cType .Type .Name ())
328
+ if testControllerName == strings .ToLower (controllerName ) && (cType .ModuleSource == moduleSource || moduleSource == anyModule ) {
329
+ WARN .Printf ("Matched empty namespace controller for %s to this %s" , controllerName , cType .ModuleSource .Name )
330
+ c = cType
331
+ found = true
332
+ break
333
+ }
334
+ }
335
+ }
336
+ }
337
+ return
338
+ }
339
+
297
340
// This is a helper that initializes (zeros) a new app controller value.
298
341
// Specifically, it sets all *revel.Controller embedded types to the provided controller.
299
342
// Returns a value representing a pointer to the new app controller.
@@ -364,6 +407,8 @@ func findControllers(appControllerType reflect.Type) (indexes [][]int) {
364
407
// Controller registry and types.
365
408
366
409
type ControllerType struct {
410
+ Namespace string // The namespace of the controller
411
+ ModuleSource * Module // The module for the controller
367
412
Type reflect.Type
368
413
Methods []* MethodType
369
414
ControllerIndexes [][]int // FieldByIndex to all embedded *Controllers
@@ -381,6 +426,32 @@ type MethodArg struct {
381
426
Type reflect.Type
382
427
}
383
428
429
+ // Adds the controller to the controllers map using its namespace, also adds it to the module list of controllers.
430
+ // If the controller is in the main application it is added without its namespace as well.
431
+ func AddControllerType (moduleSource * Module ,controllerType reflect.Type ,methods []* MethodType ) (newControllerType * ControllerType ) {
432
+ if moduleSource == nil {
433
+ moduleSource = appModule
434
+ }
435
+
436
+ newControllerType = & ControllerType {ModuleSource :moduleSource ,Type :controllerType ,Methods :methods ,ControllerIndexes :findControllers (controllerType )}
437
+ newControllerType .Namespace = moduleSource .Namespace ()
438
+ controllerName := newControllerType .Name ()
439
+
440
+ // Store the first controller only in the controllers map with the unmapped namespace.
441
+ if _ , found := controllers [controllerName ]; ! found {
442
+ controllers [controllerName ] = newControllerType
443
+ newControllerType .ModuleSource .AddController (newControllerType )
444
+ if newControllerType .ModuleSource == appModule {
445
+ // Add the controller mapping into the global namespace
446
+ controllers [newControllerType .ShortName ()] = newControllerType
447
+ }
448
+ } else {
449
+ ERROR .Printf ("Error, attempt to register duplicate controller as %s" ,controllerName )
450
+ }
451
+ TRACE .Printf ("Registered controller: %s" , controllerName )
452
+
453
+ return
454
+ }
384
455
// Method searches for a given exported method (case insensitive)
385
456
func (ct * ControllerType ) Method (name string ) * MethodType {
386
457
lowerName := strings .ToLower (name )
@@ -392,14 +463,21 @@ func (ct *ControllerType) Method(name string) *MethodType {
392
463
return nil
393
464
}
394
465
395
- var controllers = make (map [string ]* ControllerType )
466
+ // The controller name with the namespace
467
+ func (ct * ControllerType ) Name () (string ) {
468
+ return ct .Namespace + ct .ShortName ()
469
+ }
470
+
471
+ // The controller name without the namespace
472
+ func (ct * ControllerType ) ShortName () (string ) {
473
+ return strings .ToLower (ct .Type .Name ())
474
+ }
396
475
397
476
// RegisterController registers a Controller and its Methods with Revel.
398
477
func RegisterController (c interface {}, methods []* MethodType ) {
399
478
// De-star the controller type
400
479
// (e.g. given TypeOf((*Application)(nil)), want TypeOf(Application))
401
- t := reflect .TypeOf (c )
402
- elem := t .Elem ()
480
+ elem := reflect .TypeOf (c ).Elem ()
403
481
404
482
// De-star all of the method arg types too.
405
483
for _ , m := range methods {
@@ -409,10 +487,10 @@ func RegisterController(c interface{}, methods []*MethodType) {
409
487
}
410
488
}
411
489
412
- controllers [ strings . ToLower ( elem . Name ())] = & ControllerType {
413
- Type : elem ,
414
- Methods : methods ,
415
- ControllerIndexes : findControllers ( elem ),
416
- }
417
- TRACE .Printf ("Registered controller: %s" , elem .Name ())
490
+ // Fetch module for controller, if none found controller must be part of the app
491
+ controllerModule := ModuleFromPath ( elem . PkgPath (), true )
492
+
493
+ controllerType := AddControllerType ( controllerModule , elem , methods )
494
+
495
+ TRACE .Printf ("Registered controller: %s" , controllerType .Name ())
418
496
}
0 commit comments