views:

159

answers:

3

If I have a List in a Grails domain class, is there a way to override the addX() and removeX() accessors to it?

In the following example, I'd expect MyObject.addThing(String) to be called twice. In fact, the output is:

Adding thing: thing 2

class MyObject {
    static hasMany = [things: String]
    List things = []

    void addThing(String newThing) {
        println "Adding thing: ${newThing}"
        things << newThing
    }
}

class BootStrap {
    def init = { servletContext ->
            MyObject o = new MyObject().save()
            o.things << 'thing 1'
            o.addThing('thing 2')
        }
        def destroy = {
    }
}
+2  A: 

The method should be called leftShift(String), not addThing(), as documented on the Groovy operator overloading page.

Tomislav Nakic-Alfirevic
Thanks, good to know. Not sure how I can override the leftShift() method of the 'things' property though.
Alison
Thinking in a Java frame of mind, you could extend List and override it there. It might be more groovy (pun intended) to dynamically override the built in List implementation of leftShift(), but then _all_ of your List instances would follow this behaviour. Extend List?
Tomislav Nakic-Alfirevic
Maybe I'm already thinking too much like it's Java. I was hoping to perform e.g. validation in the addThing() method; would it be more groovy to create a Thing class which has constraints defined inside it?
Alison
It's addToThings BTW. I'm not sure what type of validation you're trying to do but perhaps a separate Domain class is warranted.
Matt Lachman
Thanks, Matt - addToThings() is exactly what I'm looking for. I'll consider a new Domain class too, depending on the usage.
Alison
I'm not sure what the convention is here: I'd like to accept Matt's answer, but it's only a comment. Should I repost it as a response, edit the question or accept the answer this is attached toCan anyone advise?
Alison
Matt will likely see your comment and might add it as an answer for you to accept.
Tomislav Nakic-Alfirevic
@Matt you want to add "addToThings()" as the answer?
Alison
Sorry, only just saw this. I created an answer. Thanks for the nudge! :-)
Matt Lachman
A: 

I don't understand why you expect addThing() to be called twice? Here's an explanation of your code

// things is a List, so this calls List.leftShift(Object) 
o.things << 'thing 1'

// o is an instance of MyObject, so this calls addThing()
o.addThing('thing 2')

So you're only calling addThing() once.

Don
A: 

Moving my comment to an answer:

Try using the built-in addToThings as documented here:

http://www.grails.org/doc/latest/ref/Domain%20Classes/addTo.html

Matt Lachman