Monday, May 12, 2008

Uber Generate All script for Grails

While I was creating a Grails application on an exsiting database schema I was to lazy to run grails generate-all 15 times. So I created an Uber Generate All script, which generates controllers and views for all domain classes in your application.

If you want to use it create a new script within your application (e.g. grails create-script UberGenerateAll) and copy in the code below:

import org.codehaus.groovy.grails.commons.GrailsClassUtils as GCU
import groovy.text.SimpleTemplateEngine
import org.codehaus.groovy.grails.commons.spring.GrailsRuntimeConfigurator;
import org.codehaus.groovy.grails.scaffolding.*
import org.springframework.mock.web.MockServletContext
grailsHome ="environment.GRAILS_HOME"

includeTargets << new File ( "${grailsHome}/scripts/Package.groovy" )

generateViews = true
generateController = true

target('default': "The description of the script goes here!") {
    depends( checkVersion, packageApp )
    typeName = "Domain Class"

target(doStuff: "The implementation task") {

    def beans = new grails.spring.WebBeanBuilder().beans {
        resourceHolder(org.codehaus.groovy.grails.commons.spring.GrailsResourceHolder) {
            this.resources = "file:${basedir}/grails-app/domain/**/*.groovy"
        grailsResourceLoader(org.codehaus.groovy.grails.commons.GrailsResourceLoaderFactoryBean) {
            grailsResourceHolder = resourceHolder
        def pluginResources = [] as Resource[]
        if(new File("${basedir}/plugins/*/plugin.xml").exists()) {
            pluginResources = "file:${basedir}/plugins/*/plugin.xml"

        pluginMetaManager(org.codehaus.groovy.grails.plugins.DefaultPluginMetaManager, pluginResources)
        grailsApplication(org.codehaus.groovy.grails.commons.DefaultGrailsApplication.class, ref("grailsResourceLoader"))
    appCtx = beans.createApplicationContext()    
    appCtx.servletContext = new MockServletContext()
    grailsApp = appCtx.grailsApplication

    def domainClasses = grailsApp.domainClasses

    if(!domainClasses) {
        println "Domain classes not found in grails-app/domain, trying hibernate mapped classes..."    
        try {
            def config = new GrailsRuntimeConfigurator(grailsApp, appCtx)
            appCtx = config.configure(appCtx.servletContext)                
        catch(Exception e) {
            println e.message
        domainClasses = grailsApp.domainClasses
    if(domainClasses) {
        def generator = new DefaultGrailsTemplateGenerator()
        domainClasses.each { domainClass ->
            if(generateViews) {
                event("StatusUpdate", ["Generating views for domain class ${domainClass.fullName}"])                
            if(generateController) {
                event("StatusUpdate", ["Generating controller for domain class ${domainClass.fullName}"])    
            event("StatusUpdate", ["Finished generation for domain class ${domainClass.fullName}"])            
        event("StatusFinal", ["Finished generation for domain classes"])
    else {
        event("StatusFinal", ["No domain class found"])

Then just run grails uber-generate-all and watch!

I have only tested it for Groovy domain classes, but I think it will also work for Hibernate mapped classes. Enjoy.


kouPhax said...

Excellent! Another step reducing my keystroke count.

Dave Klein said...

Uber Awesome! I've been wishing for something like this for a while. Especially when doing demos. Any chance this will make it into the core project?

Marcel Overdijk said...

Why not file a JIRA enhancement request? If you do so, please leave the link here so people who are interested could vote for it!


Daniel K said...


Please raise an issue and attach this for Grails 1.1 ;)

Dave Klein said...

JIRA request added for uber-generate-all: GRAILS-2946

Anonymous said...

I found this site using [url=][/url] And i want to thank you for your work. You have done really very good site. Great work, great site! Thank you!

Sorry for offtopic