Lee Grey
Lee Grey

Reputation: 323

Modify params before saving domain object

I needed a domain class that held a list of Strings. It seems fairly well-known that GORM can't handle this, so I've worked around it. At first I tried using getters and setters in the domain class, but that caused problems. Then I found on Stack Overflow a way to use afterLoad() and beforeValidate() to rewrite properties as shown below. This has worked well to allow me to turn the List into a String for persistence and back to a List for use in the app.

    class Entries {
        // persisted to database
        String _entry

        // exposed to app
        List entry

        static transients = ['entry']   //don't try to persist the List

        def afterLoad() {
                            // split the String from the database into a List
            entry = _entry?.split('\\|')
        }

        def beforeValidate() {
                            // join the List into a String for persisting
            _entry = entry.join('|')
        }

        static constraints = {
            _entry maxSize:4000
        }
    }

This works fine programmatically. The only problem is that the Grails scaffolding can't deal with this, even if I try to enter a pipe-delimited string. I understand the reason why is that the scaffolding creates a form field for _entry, so entry is null when it tries to save the object. And beforeValidate() relies on a List of Strings to work.

I tried to get around this in the controller, by setting params.entry = params._entry, prior to the call to new Entries(params). [I recognize that this is not a perfect solution, but this was my first pass at getting the form working.] And then I added a test in beforeValidate() to set entry = _entry if entry was null. Basically:

EntriesController.groovy:

params.entry = params._entry    // I added this line
def entriesInstance = new Entries(params)

Entries.groovy:

    def beforeValidate() {
        if( entry == null ) entry = _entry    // I added this line
        _entry = entry.join('|')
    }

I thought that would allow me to enter pipe-delimited strings into the scaffolded Create Entries form and get something into the database.

To my surprise, though, I found that both entry and _entry were null in beforeValidate(), even though I printed and verified that params contained both keys in the controller. I don't understand why this happens. How did my adding a new key to params result in nulls arriving in the domain class?

The follow-up question is, of course, what's the right way to make the scaffolded Create Entries form accept a pipe-delimited String that makes it into the database?

Upvotes: 1

Views: 1442

Answers (1)

James Kleeh
James Kleeh

Reputation: 12228

I needed a domain class that held a list of Strings. It seems fairly well-known that GORM can't handle this, so I've worked around it.

I don't agree with you here

class Xyz {

static hasMany = [entries: String]

}

Should create a seperate table to hold your list of strings (It will actually be a Set). Here are the docs

Upvotes: 2

Related Questions