views:

824

answers:

3

Removing an element from a list isn't working, which doesn't make any sense. Am I missing some special semantics peculiar to dealing with a Grails domain object list?

In controller:

def userCreate = {
    def workgroupInstance = new Workgroup()
    workgroupInstance.manager = authUserDomain
    flash.message = User.list().toString()
    def usersWithoutThisOne = User.list() - authUserDomain
    flash.message = flash.message + "removed ${authUserDomain}, new list is ${usersWithoutThisOne}"
    return ['workgroupInstance':workgroupInstance, 'users':usersWithoutThisOne]
}

Results in this being displayed in flash.message

[boogie, toogie, choogie, cookie]removed boogie, new list is [boogie, toogie, choogie, cookie]

A: 

I am not sure about this one. Don't have a Groovy interpreter available right now. But IIRC and as this article suggests, the - on lists expects to operate on two lists, i.e.,

list - other

is actually more like

list.removeAll(other)

(in Java terms), not the intended

list.remove(other)

You might try

modifiedList = originalList - [elementToRemove]
Dirk
Unfortunately not: def usersWithoutThisOne = User.list() - [authUserDomain] -->[a, b, c, d]removed a, new list is [a, b, c, d]The article says "The Groovy GDK List class supports the - operator similarly to how it supports the + operator. The following code snippet demonstrates removing one List from another using List.minus(Collection) method (there is also an overloaded version for removing an individually provided object) and using the - operator." I'm stumped.
Visionary Software Solutions
FYI, you can always get an online interpreter here: http://groovyconsole.appspot.com/
Jean Barmash
+5  A: 

Where does authUserDomain come from?

If you haven't implemented a customn .equals() on User (based on username or someother unique identified) then it may not be the same object that is returned via User.list(). An element will only be removed if it matches an existing object using .equals()

leebutts
Comes from the Acegi Spring Security Plugin. Their default Person object does not, in fact, implement equals. I've implemented an Object version and a Person version, and the result remains the same.
Visionary Software Solutions
So what do you get from:println User.list().collect{it.equals(authUserDomain)} A list containing all falses I'd expect. Which means there's something broken with your .equals() method
leebutts
I wish: [[email protected], [email protected], [email protected], [email protected]] [false, false, true, false]removed [email protected], new list is [[email protected], [email protected], [email protected], [email protected]] is my output after adding flash.message += " ${User.list().collect{it.equals(authUserDomain)}}" to the above.
Visionary Software Solutions
+1  A: 

If you intend to remove the user from the workgroup permanently, then you need to use the grails removeFrom function to get rid of classes that are stored in a has many association.

Blacktiger
Right, but this isn't intended to be a permanent removal from the db. This is just returning to a view so that a user cannot add himself to a group he already participates in (which would be redundant, obviously). I'd like to know why the list manipulation is either failing silently or "working", but not really working.
Visionary Software Solutions
I think the domain methods like list, findBy etc return a PersistentSet? I'm guessing it overrides the behaviour of minus and do nothing. How about flipping it around and collecting all the users that are not authUserDomain
leebutts
Yeah, something like User.findAllByIdNotEqual(user.id)?
Blacktiger
PersistentSets that override minus?!? Really? is this documented somewhere? It looks like that's exactly what it is, as leebutts and Blacktiger's solution works perfectly. Special props to Blacktiger for giving the Grails dynamic function, as I'm still trying to figure out what's possible with those. Good show!
Visionary Software Solutions