0

I try to validate a nested domain class instance on a command object.

Having the following command object

package demo

import grails.databinding.BindingFormat

class SaveEventCommand {

    @BindingFormat('yyyy-MM-dd')
    Date date

    Refreshment refreshment

    static constraints = {
        date validator: { date -> date > new Date() + 3}
        refreshment nullable: true
    }
}

And having the following domain class with its own constraints

package demo

class Refreshment {

    String food
    String drink
    Integer quantity

    static constraints = {
        food inList: ['food1', 'food2', 'food3']
        drink nullable: true, inList: ['drink1', 'drink2', 'drink3']
        quantity: min: 1
    }
}

I need when refreshment is not nullable the command object validates the date property and check the corresponding restrictions in refreshment instance

For now try with this code in the controller:

def save(SaveEventCommand command) {
    if (command.hasErrors() || !command.refreshment.validate()) {
        respond ([errors: command.errors], view: 'create')

        return
    }

    // Store logic goes here
}

Here through !command.refreshment.validate() I try to validate the refresh instance but I get the result that there are no errors, even when passing data that is not correct.

Thank you any guide and thank you for your time

Mario
  • 4,784
  • 3
  • 34
  • 50
  • `command.validated(); command.refreshment.validate(); if (command.hasErrors() || command.refreshment.hasErrors()) { println "hit this block"; respond ([errors: command.errors?:command?.refreshment?.errors], view: 'create')` you could try somethign like this add some verbosity to see if it hits block i also altered it so it validates first then trys to check if it has errors – V H Oct 24 '17 at 16:32

2 Answers2

1

I typically just include some code that will use a custom validator to kick off validation for any property that is composed of another command object. For example:

thePropertyInQuestion(nullable: true, validator: {val, obj, err ->
    if (val == null) return
    if (!val.validate()) {
        val.errors.allErrors.each { e ->
            err.rejectValue(
                "thePropertyInQuestion.${e.arguments[0]}",
                "${e.objectName}.${e.arguments[0]}.${e.code}",
                e.arguments,
                "${e.objectName}.${e.arguments[0]}.${e.code}"
            )
        }
    }
})

This way it's pretty clear that I want validation to occur. Plus it moves all the errors up into the root errors collection which makes things super easy for me.

Joshua Moore
  • 24,706
  • 6
  • 50
  • 73
  • Hello and thanks for replying, I checked your solution and it works as expected so the question is certainly answered, but now I have a problem with the condition that val (following your example) can be null. The condition `if (val == null) return` is not fulfilled because as inspected the value of val is an instance of Refreshment marked as `demo.Refreshment : (unsaved)` with the following properties `[food:null, drink:null, event:null, quantity:null, eventId:null]` – Mario Oct 25 '17 at 05:09
  • In order to make it work instead of `if (val == null) return true` i am using `if (!val.food && !val.quantity) return true` here I evaluate the properties food and quantity because they are in the domain class refreshments required. Any idea for a groovier solution! – Mario Oct 25 '17 at 05:31
0

Two things I could think of:

  1. Implement grails.validation.Validateable on your command object
  2. What happens when you provide an invalid date? Can you see errors while validating?
mehmood
  • 301
  • 3
  • 19
  • The command object is defined in the controller class so is marked as validetable and about the date yes if i provide an invalid date i get an error message. – Mario Oct 24 '17 at 13:06