I have what I thought was a simple hasMany association - a UserGroup hasMany Users,and the UserGroup is owned by a User:
class UserGroup {
String name
User owner
Set members = []
static hasMany = [members: User]
...
}
Fine so far. I wanted the name to be unique per owner, so originally put a constraint on name:
name unique: 'owner'
However, this also prevented updates of the same name. So I moved the constraint to beforeInsert and execute the logic expicitly:
def beforeInsert() {
boolean existing = false
UserGroup.withNewSession {
existing = UserGroup.where {
owner == this.owner && name == this.name
}.count() > 0
}
if (existing) {
this.errors.rejectValue(...)
}
return !this.hasErrors()
}
When saving a new UserGroup object with members, and beforeInsert passes, I see the hibernate actions to a) insert the UserGroup then b) insert the members.
When saving a new UserGroup object with members, and beforeInsert fails due to a duplicate name, I see only the hibernate actions to insert the members. This fails of course since there is no parent record.
Am I doing something wrong, or is it true that beforeInsert is only killing part of the save() operation and not the whole thing? And what to do?
That code on beforeInsert should be on a custom validator, but it is checking for unique name, so the right constraint should be just name unique: true (not sure what name unique: 'owner' does since it is not valid, the value should be boolean as in the specs https://docs.grails.org/latest/guide/validation.html)
And if you want to users in a group to be saved in cascade, that can be specified in the mapping field as specified on the docs https://docs.grails.org/latest/ref/Database%20Mapping/cascade.html
If the custom validator fails, or just the unique fails, the cascade save/update should not be executed.