Search code examples
grailsgrails-orm

combining criteria from params array


This example here is from the grails docs:

def emeaCriteria = {
    eq "region", "EMEA"
}
def results = Airport.withCriteria {
    emeaCriteria.delegate = delegate
    emeaCriteria()
    flights {
        like "number", "BA%"
    }
}

My webpage is passing back a checkbox group of ethnicities, returning the row ids. So what the server gets is:

ethnicity:[1, 4]

or if the user only picks one ethnicity:

   ethnicity:4

        def criteria = { params ->
//handle case where only one ethnicity is returned as just a string, not a list of strings
            def list = params.ethnicty instanceof String ? [params.ethnicty] : params.ethnicity
            if (list) {
            inList('ethnicity', list)
            }
        }

I'm getting an error: java.lang.String cannot be cast to java.lang.Enum.

If I didn't have a list I think I could figure it out. The params are sending back string values, and they need to be converted to the enum class. But within the closure, how do you convert each entry into a list to the enum?


Solution

  • I figured it out through a combination of multiple website posts and with help from dmahapatro above.

    def genderCriteria = {
        if (params.gender) {
            inList('gender', params.list('gender').collect { Gender.valueOf(it)} )
        }
    }
    

    If a webpage passes back one or more enums (a single string or a list of strings) and you want criteria to check values from the list passed back, you have to provide a list of enum types (not strings or ints).

    Here is my enum class for reference:

    public enum Gender {
        M('Male'),
        F('Female'),
        U('Unknown')
    
        final String value
    
        Gender(String value) {
            this.value = value
        }
        public String toString() {
            value
        }
        public String getKey() {
            name()
        }
        public String getValue() {
            value
        }
    
    }
    

    And my criteria builder:

            def c = MyDomain.createCriteria()
            results = c.list { 
                genderCriteria.delegate = delegate
                genderCriteria(params)
    
            }
    

    Even if no values are passed back for the gender field, it still works (because of the if statement in genderCriteria.

    It may not be the best or cleanest solution, but it does work.