为grails控制器使用自定义脚手架?

为grails控制器使用自定义脚手架?,grails,groovy,code-generation,metaprogramming,Grails,Groovy,Code Generation,Metaprogramming,我想了解更多关于定制grails控制器生成的信息,但我找不到任何文档 具体地说,我的动机是使用一个遗留数据库,这是只读的。所以我想定制代码生成,这样,如果某个域类在某个包中,例如:toppackage.readonly,那么只生成只读代码,只生成控制器上的list和show方法 我已经对它做了一些研究,但我不确定他们是如何解析模板的。它们包含标记,并且似乎对语义空白敏感 我知道脚手架的设计意图是给你一个起点,但通常情况下,有些东西会在以后被重新审视和改变,而再次再生似乎是浪费。还有一些特定于属于

我想了解更多关于定制grails控制器生成的信息,但我找不到任何文档

具体地说,我的动机是使用一个遗留数据库,这是只读的。所以我想定制代码生成,这样,如果某个域类在某个包中,例如:toppackage.readonly,那么只生成只读代码,只生成控制器上的list和show方法

我已经对它做了一些研究,但我不确定他们是如何解析模板的。它们包含标记,并且似乎对语义空白敏感

我知道脚手架的设计意图是给你一个起点,但通常情况下,有些东西会在以后被重新审视和改变,而再次再生似乎是浪费。还有一些特定于属于代码生成阶段的项目的约定。在我们的例子中,有一些属于代码生成阶段的安全需求

如何将变量注入代码模板

如何评估标签?它是OGNL的一种形式吗

目前,我采用了一些可怕的丑陋方式来实现这一点,方法是将域类放在名称为readonly的包中,并将其放在控制器模板中:

<%=!(packageName=~/\readonly/) ? """    def save = {\n
        def ${propertyName} = new ${className}(params)\n
        if (${propertyName}.save(flush: true)) {\n
            flash.message = \"\${message(code: 'default.created.message', args: [message(code: '${domainClass.propertyName}.label', default: '${className}'), ${propertyName}.id])}\"\n
            redirect(action: \"show\", id: ${propertyName}.id)\n
        }\n
        else {\n
            render(view: \"create\", model: [${propertyName}: ${propertyName}])\n
        }
    }""" : ''%>

以下各项应起作用:

执行
grails install templates
安装并修改模板()


def保存={
def${propertyName}=new${className}(参数)
if(${propertyName}.save(flush:true)){
flash.message=“\${message(代码:'default.created.message',args:[消息(代码:'${domainClass.propertyName}.label',默认:'${className}'),${propertyName}.id])”
重定向(操作:“显示”,id:${propertyName}.id)
}
否则{
渲染(视图:“创建”,模型:[${propertyName}:${propertyName}])
}
}
您不必添加
\n
或转义
${..}
,除非您想在结果中生成这些内容(如消息)

简而言之:

  • 之外的所有内容都会打印到结果中
  • 在搭建过程中,对
    中的所有内容进行评估
  • ${..}
    中的所有变量在
  • 所有变量在
    中解析时,不需要
    ${..}
  • 当希望将变量作为变量而不是解析值生成时,需要对其进行转义(
    \${..}

您试图注入的变量是什么?仅供参考……您可以随时查看GRAILS_HOME/scripts/GenerateController.groovy脚本,了解它是如何发挥作用的。您可以看到它最终使用DefaultGrailTemplateGenerator()来评估模板。
<% if (!packageName.contains("readonly")) { %>
    def save = {
        def ${propertyName} = new ${className}(params)
        if (${propertyName}.save(flush: true)) {
            flash.message = "\${message(code: 'default.created.message', args: [message(code: '${domainClass.propertyName}.label', default: '${className}'), ${propertyName}.id])}"
            redirect(action: "show", id: ${propertyName}.id)
        }
        else {
            render(view: "create", model: [${propertyName}: ${propertyName}])
        }
    }
<% } %>