2011-09-14 26 views
2

我有一個應用程序使用grails多租戶內核插件來託管多個版本的網站。我希望能夠爲每個站點創建自定義的GSP,而不僅限於簡單的蒙皮允許我執行的操作。從本質上講,我希望能有我grails-app/views文件夾的樣子是這樣的:在Grails多租戶核心插件中使用多個GSP模板/皮膚?

views 
| 
|__template1 
| | 
| |__layouts 
| | | 
| | |__main.gsp 
| | 
| |__controller1 
|  |  
|  |__index.gsp 
| 
|__template 2 
    | 
    |__layouts 
    | | 
    | |__main.gsp 
    | 
    |__controller1 
     |  
     |__index.gsp 

,然後配置特定租戶使用一組特定的GSP的。我使用的是一個DNS解析器,它保存在我的數據庫中,所以我可能會將一個屬性添加到DomainTenantMap域類中,該類將一個templateDir屬性分配給特定租戶,並在我的GSP和控制器中遍佈所有地方。 (其次是'不能...得到...乾淨'的感覺)

我還沒有找到一個現有的插件提供此功能的任何成功。我所考慮的其他選項似乎涉及定製相當核心的grails(渲染標記,模板引擎等),這讓我感到緊張。

我意識到這是一個相當廣泛的問題;讚賞具體的解決方案和一般建議。

編輯:

我發現了另一個可能的方法通過創建一個插件和元編程的一個新方法:

def configureTemplateRenderer(application, applicationContext) { 
    for (controllerClass in application.controllerClasses) { 

     controllerClass.metaClass.newRender = { args -> 
      println 'something' 
      if(args.view) { 
       args.view = "/somedir/${args.view}" 
      } 
      if(args.template) { 
       args.template = "/somedir/${args.template}" 
      } 
      delegate.render(args) 
     } 
    } 
} 

這僅僅是一個概念證明,看看我可以調用標準render通過我的新方法(我可以)。理想情況下,我可以完全覆蓋render方法以基於某種租戶/模板映射(未顯示)修改args.viewargs.template屬性。但是,我一直無法成功覆蓋render方法,所以這個解決方案實際上只比在一些路徑變量中調用render更好。

解決方案!

我最終創建了一個單獨的插件,基本上歸結爲用於檢查租戶/模板映射的渲染方法。不過測試,但到目前爲止,它看起來很有希望,這裏是它的要點是:

def overrideRender = { application -> 
    for (controllerClass in application.controllerClasses) { 
     def original = controllerClass.metaClass.getMetaMethod("render", [Map] as Class[]) 
     def originalRender = original.getClosure() 

     controllerClass.metaClass.originalRender = originalRender 

     controllerClass.metaClass.render = { Map atts -> 
      def templatePath = // some code to lookup against a TenantTenantMap 
      if(templatePath) { 
       if(atts.view) { 
        atts.view = "${templatePath}${atts?.view}" 
       } 
       if(atts.template) { 
        atts.template = "${templatePath}${atts?.template}" 
       } 
      } 
      delegate.originalRender(atts) 
     } 
    } 
} 

唯一的缺點是,我必須使用比我想稍微醜陋的目錄結構:views/controller/$template/action,而不是將所有的模板GSPS一起下views/$template/controller/action。我想我現在可以接受這一點。

回答

0

我使用的解決方案:

def overrideRender = { application -> 
    for (controllerClass in application.controllerClasses) { 
     def original = controllerClass.metaClass.getMetaMethod("render", [Map] as Class[]) 
     def originalRender = original.getClosure() 

     controllerClass.metaClass.originalRender = originalRender 

     controllerClass.metaClass.render = { Map atts -> 
      def templatePath = // some code to lookup against a TenantTenantMap 
      if(templatePath) { 
       if(atts.view) { 
        atts.view = "${templatePath}${atts?.view}" 
       } 
       if(atts.template) { 
        atts.template = "${templatePath}${atts?.template}" 
       } 
      } 
      delegate.originalRender(atts) 
     } 
    } 
} 
相關問題