Ad-Hockery

ad-hockery: /ad·hok'@r·ee/, n.
Gratuitous assumptions... which lead to the appearance of semi-intelligent behavior but are in fact entirely arbitrary. Jargon File

Using a custom data binder with Grails domain objects

Yesterday I read a post by Stefan Armbruster on how to register a custom data binder to lookup Grails domain objects by any arbitrary property. I wanted to go a little further so that I could not only bind existing domain instances but create new ones as well.

For example, let’s say I have Artist and Album domain classes where Artist hasMany Albums and Album belongsTo Artist. Artist has a name property that is unique. On my create album page I want to be able to type in the artist name and have the save action in the controller automatically lookup an existing Artist instance or create a new one if it doesn’t exist. Doing this I don’t want to have to add or change anything in the save action itself - I could theoretically use dynamic scaffolding.

Adapting Stefan’s PropertyEditor implementation I created this:

import java.beans.PropertyEditorSupport
import org.apache.commons.lang.StringUtils

class DomainClassLookupPropertyEditor extends PropertyEditorSupport {

    Class domainClass
    String property

    String getAsText() {
        value."$property"
    }

    void setAsText(String text) {
        value = domainClass."findBy${StringUtils.capitalize(property)}"(text)
        if (!value) {
            value = domainClass.newInstance((property): text)
        }
    }
}

The crucial change is the if (!value) block which creates the new instance and populates the relevant property.

To make everything work I just need to:

  1. Add the PropertyEditorRegistrar and place it in resources.groovy as per Stefan’s post.

  2. Have a text input or autocompleter with the name "artist" in my create album form.

  3. Add artist cascade: "save-update" to the mapping block in Album so that when the Album is saved the new Album will get saved as well.

Web Statistics