I have an issue where my domain class has two potential mutually exclusive external keys, either a serial number or a legacy lookup value.
Since I'm not sure which one I'll have for any given entry, I've made them both nullable and added custom validation to try to ensure I have one and only one value.
package myproject
class Sample {
String information
String legacyLookup
String serialNumber
static constraints = {
information(nullable: true)
legacyLookup(nullable: true)
serialNumber(nullable: true)
legacyLookup validator: {
return ((serialNumber != null && legacyLookup == null) || (serialNumber == null && legacyLookup != null))
}
serialNumber validator: {
return ((serialNumber != null && legacyLookup == null) || (serialNumber == null && legacyLookup != null))
}
}
}
I created the default CRUD screens and tried to create an entry for this domain class
information: Blah Blah
serialNumber:
legacyLookup: BLAHINDEX123
This dies in the validator with the following message:
No such property: serialNumber for class: myproject.Sample
What am I missing?
Having each property in there multiple times is not necessary; in fact you only need one of them actually constrained. Also you can't just reference properties directly by their name. There are objects that are passed to the constraint closure that are used to get at the values (see the docs). Probably the simplest way I've found to do this is as follows:
class Sample {
String information
String legacyLookup
String serialNumber
static constraints = {
information(nullable: true)
legacyLookup(validator: {val, obj->
if( (!val && !obj.serialNumber) || (val && obj.serialNumber) ) {
return 'must.be.one'
}
})
}
}
And then have an entry in the messages.properties file like this:
must.be.one=Please enter either a serial number or a legacy id - not both
Or you could have separate messages for each condition - both are entered, or both are blank like this:
legacyLookup(validator: {val, obj->
if(!val && !obj.serialNumber) {
return 'must.be.one'
}
if(val && obj.serialNumber) {
return 'only.one'
}
})
And then have two messages in message.properties:
only.one=Don't fill out both
must.be.one=Fill out at least one...
You don't need to return anything from the constraint if there is no error...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With