Anuj Aneja
Anuj Aneja

Reputation: 1344

Using config driven logic in createCriteria grails

I have requirement in which i need some logic of criteria query to be config driven. Earlier i used to query like : e.g.:

User.createCriteria().list{
     or{ 
        eq('username',user.username)
        eq('name',user.name)
     }
}

But, i need this to be configurable in my use case so, i try this code snippet.

def criteriaCondition= grailsApplication.config.criteriaCondition?:{user->
         or{
           eq('username',user.username)
           eq('name',user.name)   
         }
}

User.createCriteria().list{criteriaCondition(user)}

But, This doesn't work for me. I am getting missing method exception for "or" I tried few solution from some sources but it didn't worked for me.

So, can anyone help me :

1) How to make the above given code work. 2) Any other better way for my use case.

Thanks in advance!!!

Upvotes: 1

Views: 312

Answers (2)

Ian Roberts
Ian Roberts

Reputation: 122364

The way the criteria builder mechanism works, the list method expects to be passed a closure which it will call, whereas your current code is calling the criteriaCondition closure itself rather than letting the criteria builder call it. "Currying" will help you here: given

def criteriaCondition= grailsApplication.config.criteriaCondition?:{user->
         or{
           eq('username',user.username)
           eq('name',user.name)   
         }
}

instead of saying

User.createCriteria().list{criteriaCondition(user)}

you say

User.createCriteria().list(criteriaCondition.curry(user))

(note the round brackets rather than braces).

The curry method of Closure returns you another Closure with some or all of its arguments "pre-bound" to specific values. For example

def add = {a, b -> a + b}
def twoPlus = add.curry(2) // gives a closure equivalent to {b -> 2 + b}
println twoPlus(3) // prints 5

In your case, criteriaCondition.curry(user) gives you a zero-argument closure that you can pass to criteria.list. You can curry as many arguments as you like (up to the number that the closure can accept).

Upvotes: 2

Kamil Mikolajczyk
Kamil Mikolajczyk

Reputation: 911

you have to pass criteriaBuilder object to the closure, something like this:

def criteriaCondition = grailsApplication.config.criteriaCondition ?: { cb, user ->
     cb.or{
       cb.eq('username',user.username)
       cb.eq('name',user.name)   
     }
}

def criteriaBuilder = User.createCriteria()

criteriaBuilder.list{
    criteriaCondition(criteriaBuilder, user)
}

obviously, closure in the Config.groovy also has to have the same parameters list, including cb

Upvotes: 2

Related Questions