Kevin Stricker
Kevin Stricker

Reputation: 17388

How can I assign a nested structure using NodeBuilder in Grails in Config.groovy?

I'm trying to graph a site's structure for navigation using builder syntax inside Config.groovy as follows:

com.foo.demo.siteStructure = NodeBuilder.newInstance().site() {
    item(controller: 'sample', action: 'list')
    item(controller: 'address', action: 'list') {
        item(controller: 'city', action: 'list', title: 'Municipality')
    }
}

The object this produces in the debugger is:

site[attributes={}; value=[item[attributes={controller=sample, action=list}; value=[]], item[attributes={controller=city, action=list, title=Municipality}; value=[]]]]

So it appears to be only going one level deep, and replacing the second item with the one it contains.

I get the same single level of nesting if I pre-define an Item object and use ObjectGraphBuilder:

class Item {
    String controller
    String action
    String title
    SiteNode parent
    List<Item> items = []
}

So, it would appear the ConfigSlurper is mangling the result somehow. Is there a better way to mark up a nested structure as a config value?

Upvotes: 2

Views: 575

Answers (1)

Kevin Stricker
Kevin Stricker

Reputation: 17388

I did manage to get this working by adapting how the resource plugin reads the configuration. I first changed the configured value to a regular closure:

com.foo.demo.siteStructure = {
    root {
        item(controller: 'sample', action: 'list')
        item(controller: 'address', action: 'list') {
            item(controller: 'city', action: 'list', title: 'Municipality')
        }
    }
}

Then did the actual processing of the dsl inside a singleton (something like this):

Node root
def menus = grailsApplication.config.com.foo.demo.siteStructure
if (menus instanceof Closure) {
    def builder = new NodeBuilder()
    menus.delegate = builder
    menus.resolveStrategy = Closure.DELEGATE_FIRST
    root = menus()
}

Upvotes: 3

Related Questions