From 8c470e46a2227c52d3b26b2355ab6b6aa8b1cd1a Mon Sep 17 00:00:00 2001 From: "Gerasimos (Makis) Maropoulos" Date: Wed, 6 May 2020 08:00:56 +0300 Subject: [PATCH] mvc controllers and methods: provide mvc.Application automatically Former-commit-id: 991d8e72c3c231813a455dd0680cd8a83b82abb1 --- HISTORY.md | 1 + mvc/controller_test.go | 23 ++++++++++++++++++++++- mvc/mvc.go | 39 +++++++++++++++++++++++++++++++++++++-- 3 files changed, 60 insertions(+), 3 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index 260a261e..e531574e 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -145,6 +145,7 @@ Prior to this version the `iris.Context` was the only one dependency that has be | Type | Maps To | |------|:---------| +| [*mvc.Application](https://pkg.go.dev/github.com/kataras/iris/v12/mvc?tab=doc#Application) | Current MVC Application | | [iris.Context](https://pkg.go.dev/github.com/kataras/iris/v12/context?tab=doc#Context) | Current Iris Context | | [*sessions.Session](https://pkg.go.dev/github.com/kataras/iris/v12/sessions?tab=doc#Session) | Current Iris Session | | [context.Context](https://golang.org/pkg/context/#Context) | [ctx.Request().Context()](https://golang.org/pkg/net/http/#Request.Context) | diff --git a/mvc/controller_test.go b/mvc/controller_test.go index 1919b08c..3b695dbc 100644 --- a/mvc/controller_test.go +++ b/mvc/controller_test.go @@ -506,7 +506,7 @@ type testControllerNotCreateNewDueManuallySettingAllFields struct { } func (c *testControllerNotCreateNewDueManuallySettingAllFields) AfterActivation(a AfterActivation) { - if n := len(a.DependenciesReadOnly()) - len(hero.BuiltinDependencies); n != 1 { + if n := len(a.DependenciesReadOnly()) - len(hero.BuiltinDependencies) - 1; /* Application */ n != 1 { c.T.Fatalf(`expecting 1 dependency; - the 'T' and the 'TitlePointer' are manually binded (nonzero fields on initilization) - controller has no more than these two fields, it's a singleton @@ -624,3 +624,24 @@ func TestControllersInsideControllerDeep(t *testing.T) { e := httptest.New(t, app) e.GET("/something").Expect().Status(httptest.StatusOK).Body().Equal("foo bar") } + +type testApplicationDependency struct { + App *Application +} + +func (c *testApplicationDependency) Get() string { + return c.App.Name +} + +func TestApplicationDependency(t *testing.T) { + app := iris.New() + m := New(app).SetName("app1") + m.Handle(new(testApplicationDependency)) + + m2 := m.Clone(app.Party("/other")).SetName("app2") + m2.Handle(new(testApplicationDependency)) + + e := httptest.New(t, app) + e.GET("/").Expect().Status(httptest.StatusOK).Body().Equal("app1") + e.GET("/other").Expect().Status(httptest.StatusOK).Body().Equal("app2") +} diff --git a/mvc/mvc.go b/mvc/mvc.go index 6edfb817..9c6944cc 100644 --- a/mvc/mvc.go +++ b/mvc/mvc.go @@ -25,6 +25,8 @@ import ( // See `mvc#New` for more. type Application struct { container *hero.Container + // This Application's Name. Keep names unique to each other. + Name string Router router.Party Controllers []*ControllerActivator @@ -32,10 +34,34 @@ type Application struct { } func newApp(subRouter router.Party, container *hero.Container) *Application { - return &Application{ + app := &Application{ Router: subRouter, container: container, } + + // Register this Application so any field or method's input argument of + // *mvc.Application can point to the current MVC application that the controller runs on. + registerBuiltinDependencies(container, app) + return app +} + +// See `hero.BuiltinDependencies` too, here we are registering dependencies per MVC Application. +func registerBuiltinDependencies(container *hero.Container, deps ...interface{}) { + for _, dep := range deps { + depTyp := reflect.TypeOf(dep) + for i, dependency := range container.Dependencies { + if dependency.Static { + if dependency.DestType == depTyp { + // Remove any existing before register this one (see app.Clone). + copy(container.Dependencies[i:], container.Dependencies[i+1:]) + container.Dependencies = container.Dependencies[:len(container.Dependencies)-1] + break + } + } + } + + container.Register(dep) + } } // New returns a new mvc Application based on a "party". @@ -44,7 +70,7 @@ func newApp(subRouter router.Party, container *hero.Container) *Application { // // Example: `New(app.Party("/todo"))` or `New(app)` as it's the same as `New(app.Party("/"))`. func New(party router.Party) *Application { - return newApp(party, party.ConfigureContainer().Container) + return newApp(party, party.ConfigureContainer().Container.Clone()) } // Configure creates a new controller and configures it, @@ -78,6 +104,15 @@ func (app *Application) Configure(configurators ...func(*Application)) *Applicat return app } +// SetName sets a unique name to this MVC Application. +// Used for logging, not used in runtime yet, but maybe useful for future features. +// +// It returns this Application. +func (app *Application) SetName(appName string) *Application { + app.Name = appName + return app +} + // Register appends one or more values as dependencies. // The value can be a single struct value-instance or a function // which has one input and one output, the input should be