Reputation: 1344
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
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
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