I often find myself repeating the same namedQuery pattern in my domain classes. For example, I recently had the need of defining a lot of domain classes with the following structure
class Dummy {
String foo
Date validFrom
Date validTo
static constraints = {
}
}
where the two properties validFrom and validTo represent the time interval in which the object is valid.
For every such class I define the valid() namedQuery in order to fetch all the valid instances to date
static namedQueries = {
valid {
def now = new Date()
lt 'validFrom', now
gt 'validTo', now
}
}
Obviously, this solution is not very DRY, since the same query is spread over all my classes.
So, I decided to refactor my code a little and I came up with a much cleaner solution (I suspect I could do better, but I'm quite satisifed with that).
I define a QueryHolder class like that
class QueryHolder {
static def nowInRange(fromField, toField) {
{it ->
def now = new Date()
lt fromField, now
gt toField, now
}
}
}
It simply declares a static method that returns a closure to plug in the namedQuery structure.
The two parameters fromField and toField make the method flexible enough to be reused across classes which declares slightly different member field to track their validity.
static namedQueries = {
valid(QueryHolder.nowInRange('validFrom', 'validTo'))
}
Now, I can invoke valid() on my Dummy class to obtain all valid Dummies to date :)
def result = Dummy.valid().list()
Here's the complete Dummy listing
class Dummy {
String foo
Date validFrom
Date validTo
static constraints = {
}
static namedQueries = {
valid(QueryHolder.nowInRange('validFrom', 'validTo'))
}
}
class QueryHolder {
static def nowInRange(fromField, toField) {
{it ->
def now = new Date()
lt fromField, now
gt toField, now
}
}
}