@@ -7,7 +7,6 @@ package revel
7
7
import (
8
8
"errors"
9
9
"fmt"
10
- "go/build"
11
10
"io"
12
11
"net/http"
13
12
"os"
@@ -92,10 +91,19 @@ func (c *Controller) setStatusIfNil(status int) {
92
91
//
93
92
// This action will render views/Users/ShowUser.html, passing in an extra
94
93
// key-value "user": (User).
94
+ //
95
+ // This is the slower magical version which uses the runtime
96
+ // to determine
97
+ // 1) Set c.ViewArgs to the arguments passed into this function
98
+ // 2) How to call the RenderTemplate by building the following line
99
+ // c.RenderTemplate(c.Name + "/" + c.MethodType.Name + "." + c.Request.Format)
100
+ //
101
+ // If you want your code to run faster it is recommended you add the template values directly
102
+ // to the c.ViewArgs and call c.RenderTemplate directly
95
103
func (c * Controller ) Render (extraViewArgs ... interface {}) Result {
96
104
c .setStatusIfNil (http .StatusOK )
97
105
98
- // Get the calling function name .
106
+ // Get the calling function line number .
99
107
_ , _ , line , ok := runtime .Caller (1 )
100
108
if ! ok {
101
109
ERROR .Println ("Failed to get Caller information" )
@@ -278,10 +286,11 @@ func (c *Controller) Message(message string, args ...interface{}) (value string)
278
286
func (c * Controller ) SetAction (controllerName , methodName string ) error {
279
287
280
288
// Look up the controller and method types.
281
- var ok bool
282
- if c .Type , ok = controllers [strings .ToLower (controllerName )]; ! ok {
289
+ if c .Type = ControllerTypeByName (controllerName , anyModule ); c .Type == nil {
283
290
return errors .New ("revel/controller: failed to find controller " + controllerName )
284
291
}
292
+
293
+ // Note method name is case insensitive search
285
294
if c .MethodType = c .Type .Method (methodName ); c .MethodType == nil {
286
295
return errors .New ("revel/controller: failed to find action " + methodName )
287
296
}
@@ -294,6 +303,26 @@ func (c *Controller) SetAction(controllerName, methodName string) error {
294
303
295
304
return nil
296
305
}
306
+ func ControllerTypeByName (controllerName string , moduleSource * Module ) (c * ControllerType ) {
307
+ var found bool
308
+ if c , found = controllers [controllerName ]; ! found {
309
+ // Backup, passed in controllerName should be in lower case, but may not be
310
+ if c , found = controllers [strings .ToLower (controllerName )]; ! found {
311
+ INFO .Printf ("Cannot find controller name '%s' in controllers map " , controllerName )
312
+ // Search for the controller by name
313
+ for _ , cType := range controllers {
314
+ testControllerName := strings .ToLower (cType .Type .Name ())
315
+ if testControllerName == strings .ToLower (controllerName ) && (cType .ModuleSource == moduleSource || moduleSource == anyModule ) {
316
+ WARN .Printf ("Matched empty namespace controller for %s to this %s" , controllerName , cType .ModuleSource .Name )
317
+ c = cType
318
+ found = true
319
+ break
320
+ }
321
+ }
322
+ }
323
+ }
324
+ return
325
+ }
297
326
298
327
// This is a helper that initializes (zeros) a new app controller value.
299
328
// Specifically, it sets all *revel.Controller embedded types to the provided controller.
@@ -365,6 +394,7 @@ func findControllers(appControllerType reflect.Type) (indexes [][]int) {
365
394
// Controller registry and types.
366
395
367
396
type ControllerType struct {
397
+ Namespace string // The namespace of the controller
368
398
ModuleSource * Module // The module for the controller
369
399
Type reflect.Type
370
400
Methods []* MethodType
@@ -383,6 +413,30 @@ type MethodArg struct {
383
413
Type reflect.Type
384
414
}
385
415
416
+ func AddControllerType (moduleSource * Module ,controllerType reflect.Type ,methods []* MethodType ) (newControllerType * ControllerType ) {
417
+ if moduleSource == nil {
418
+ moduleSource = appModule
419
+ }
420
+
421
+ newControllerType = & ControllerType {ModuleSource :moduleSource ,Type :controllerType ,Methods :methods ,ControllerIndexes :findControllers (controllerType )}
422
+ newControllerType .Namespace = moduleSource .Namespace ()
423
+ controllerName := newControllerType .Name ()
424
+
425
+ // Store the first controller only in the controllers map with the unmapped namespace.
426
+ if _ , found := controllers [controllerName ]; ! found {
427
+ controllers [controllerName ] = newControllerType
428
+ newControllerType .ModuleSource .AddController (newControllerType )
429
+ if newControllerType .ModuleSource == appModule {
430
+ // Add the controller mapping into the global namespace
431
+ controllers [newControllerType .ShortName ()] = newControllerType
432
+ }
433
+ } else {
434
+ ERROR .Printf ("Error, attempt to register duplicate controller as %s" ,controllerName )
435
+ }
436
+ TRACE .Printf ("Registered controller: %s" , controllerName )
437
+
438
+ return
439
+ }
386
440
// Method searches for a given exported method (case insensitive)
387
441
func (ct * ControllerType ) Method (name string ) * MethodType {
388
442
lowerName := strings .ToLower (name )
@@ -394,6 +448,16 @@ func (ct *ControllerType) Method(name string) *MethodType {
394
448
return nil
395
449
}
396
450
451
+ // The controller name without the namespace
452
+ func (ct * ControllerType ) Name () (string ) {
453
+ return ct .Namespace + ct .ShortName ()
454
+ }
455
+
456
+ // The controller name with the namespace
457
+ func (ct * ControllerType ) ShortName () (string ) {
458
+ return strings .ToLower (ct .Type .Name ())
459
+ }
460
+
397
461
var controllers = make (map [string ]* ControllerType )
398
462
399
463
// RegisterController registers a Controller and its Methods with Revel.
@@ -409,30 +473,11 @@ func RegisterController(c interface{}, methods []*MethodType) {
409
473
arg .Type = arg .Type .Elem ()
410
474
}
411
475
}
412
- path := elem .PkgPath ()
413
- gopathList := filepath .SplitList (build .Default .GOPATH )
414
- var controllerModule * Module
415
-
416
- // See if the path exists in the module based
417
- for i := range Modules {
418
- found := false
419
- for _ , gopath := range gopathList {
420
- if strings .HasPrefix (gopath + "/src/" + path , Modules [i ].Path ) {
421
- controllerModule = Modules [i ]
422
- found = true
423
- break
424
- }
425
- }
426
- if found {
427
- break
428
- }
429
- }
430
476
431
- controllers [strings .ToLower (elem .Name ())] = & ControllerType {
432
- ModuleSource : controllerModule ,
433
- Type : elem ,
434
- Methods : methods ,
435
- ControllerIndexes : findControllers (elem ),
436
- }
437
- TRACE .Printf ("Registered controller: %s" , elem .Name ())
477
+ // Fetch module for controller, if none found controller must be part of the app
478
+ controllerModule := ModuleFromPath (elem .PkgPath (), true )
479
+
480
+ controllerType := AddControllerType (controllerModule ,elem ,methods )
481
+
482
+ TRACE .Printf ("Registered controller: %s" , controllerType .Name ())
438
483
}
0 commit comments