Grails custom validator for domain class

2019-04-10 17:49发布

I have a restriction so there could be no more than ConfigurationHolder.config.support.reminder.web.person.max object stored. I didn't find how to add a validator which doesn't relate on particular property. So for now I implemented it in this way. Do you guys have any ideas how to make it better?

package support.reminder.web

import org.codehaus.groovy.grails.commons.ConfigurationHolder;

class Person {

    String firstName
    String lastName
    String email
    Date lastDutyDate

    static constraints = {
        firstName(blank: false)
        lastName(blank: false)
        email(blank: false, email: true)
        lastDutyDate(nullable: true)
        id validator: {val ->
        if (val)
            Person.count() <= ConfigurationHolder.config.support.reminder.web.person.max
        else
            Person.count() < ConfigurationHolder.config.support.reminder.web.person.max
    }
    }

    String toString() {
        "[$firstName $lastName, $email, $lastDutyDate]"
    }
}

3条回答
2楼-- · 2019-04-10 18:10

You can use the Grails Custom Constraints Plugin to manage your validation implementation. Then you can call your own constraint just like the predefined Grails constraints:

package support.reminder.web

import org.codehaus.groovy.grails.commons.ConfigurationHolder as CH

class Person {

    String firstName
    String lastName
    String email
    Date lastDutyDate

    static constraints = {
        firstName(blank: false)
        lastName(blank: false)
        email(blank: false, email: true)
        lastDutyDate(nullable: true)
        id(maxRows: CH.config.support.reminder.web.person.max)
    }

}

Alternatively, if you don't want to rely on 3rd Party Plugins you can implement the logic of your custom validator within a Service method but call it from the custom validator in the Domain:

package support.reminder.web

import org.codehaus.groovy.grails.commons.ConfigurationHolder as CH

class Person {

    def validationService
    String firstName
    String lastName
    String email
    Date lastDutyDate

    static constraints = {
        firstName(blank: false)
        lastName(blank: false)
        email(blank: false, email: true)
        lastDutyDate(nullable: true)
        id (validator: {val ->
           validationService.validateMaxRows(val, CH.config.support.reminder.web.person.max)
        }
    }

}
查看更多
祖国的老花朵
3楼-- · 2019-04-10 18:30

I recommend you using a service function, like personService.addPerson(). Then check the constraint before you save a new object. It will benefit if you get more complicated constraint, such as when it related many domain objects, for example.

The use of a validator for restricting the number of object is actually not very good if concerning about the meaning of validator: the object is valid, only the number of objects is too large.

In short: the logical code goes to the service.

查看更多
何必那么认真
4楼-- · 2019-04-10 18:32

I don't have a better idea, but I do suggest that maybe you need to check for < not <=. I think that when validating your object, it has not yet been stored in the DB, so it will not be included in Person.count(). I reckon that <= would cause it to pass the validation then be saved, then you would be violating the rule.

查看更多
登录 后发表回答