1

I have a Grails domain object that looks like this:

class Product {
    Boolean isDiscounted = false
    Integer discountPercent = 0

    static constraints = {
        isDiscounted(nullable: false)
        discountPercent(range:0..99)
}

I'd like to add a validator to discountPercent that will only validate if isDiscounted is true, something like this:

validator: { val, thisProduct ->
    if (thisProduct.isDiscounted) {
        // need to run the default validator here
        thisProduct.discountPercent.validate() // not actual working code
    } else {
        thisProduct.discountPercent = null // reset discount percent
}

Does anyone know how I can do this?

Daniel T.
  • 37,212
  • 36
  • 139
  • 206
  • That is exactly how you do it, put that one on the discountPercent property and you should be good to go. What is it that doesn't work? Do you get any exceptions? – Oliver Tynes May 17 '12 at 22:59
  • `discountPercent.validate()` does not exist. – Daniel T. May 17 '12 at 23:33
  • 1
    validate() works on a domain object as a whole not on an individual field so you want thisProduct.validate() – Steve May 18 '12 at 00:48
  • Yeah sorry about that, I skimmed your actual domain object and assumed that the discountPercent was another entity. – Oliver Tynes May 18 '12 at 02:54
  • Did you actually mean `thisProduct.discountPercent = null` or did you mean `==` ? Don't set values in validators. You CAN set values in a `beforeInsert` or `beforeUpdate` instead. – Nancy Deschênes Aug 23 '17 at 16:24

1 Answers1

1

This is more or less what you need (on the discountPercent field):

validator: { val, thisProduct ->
if (thisProduct.isDiscounted)
    if (val < 0) {
        return 'range.toosmall' //default code for this range constraint error
    }
    if (99 < val) {
        return 'range.toobig' //default code for this range constraint error

} else {
    return 'invalid.dependency'
}

You can't both have a special validator that relies on something else and have a special validator, as you can't run a single validator on a field (that I know of), only on single properties. But if you run a validation on this property, you'll depend on yourself and go into endless recursion. Therefore I added the range check manually. In your i18n files you can set up something like full.packet.path.FullClassName.invalid.dependency=Product not discounted.

Good luck!

Oliver Tynes
  • 954
  • 4
  • 11
  • 1
    I strongly suggest you scrap your idea of setting the percentage to null in the validator, the validator is for validation, not business logic. Do a `if(!product.validate()) { product.discountPercent = null }` kind of solution instead in your controller or wherever this code is. – Oliver Tynes May 18 '12 at 03:06