giovedì 19 maggio 2011

Narrowing properties returned from Grails Criteria

These snippets show a nice feature that I think could be better documented in Grails docs: the use of projections closure to narrow properties returned from criteria.

package org.unnoware
class Author {
static hasMany = ['books':Book]
String name
Integer age
String address
static constraints = {
}
}
view raw Author.groovy hosted with ❤ by GitHub
package org.unnoware
import grails.plugin.spock.IntegrationSpec
class AuthorSpec extends IntegrationSpec {
def "select a subset of Author properties"() {
setup:
(1..3).collect { Author.build(name : "author #$it", age : 30 + it) }
when: "querying for author name and age"
def results = Author.withCriteria{
projections{
property 'name', 'authorName'
property 'age', 'authorAge'
}
gt 'authorAge', 31
}
then: "only authors with age > 31 are returned"
results.size() == 2
and: "returned only name and age properties"
results[i].size() == 2
and:
results[i][0] == name
results[i][1] == age
where:
i | name | age
0 | 'author #2' | 32
1 | 'author #3' | 33
}
}


And it works with associations too:

package org.unnoware
class Book {
static belongsTo = ['author': Author]
String title
Integer pages
BigDecimal price
static constraints = {
}
}
view raw Book.groovy hosted with ❤ by GitHub
package org.unnoware
import grails.plugin.spock.IntegrationSpec
class BookSpec extends IntegrationSpec {
def "select a subset of Book and Author properties"() {
setup:
(1..3).collect { authorIdx ->
def author = Author.build(name : "author #$authorIdx", age : 30 + authorIdx)
(1..authorIdx).collect{ bookIdx ->
Book.build(author : author, title : "Book #$bookIdx from ${author.name}", pages : bookIdx * 100, price : bookIdx * 1000.0)
}
}
when: "querying for author name and age "
def results = Book.withCriteria{
projections{
author{
property 'name', 'authorName'
property 'age', 'authorAge'
}
property 'title', 'title'
property 'price', 'price'
}
gt 'authorAge', 31
le 'price', 2000.0
}
then: "only the authors with age > 31 with books priced 2000 or less"
results.size() == 4
and: "returned author name and age with book title and price properties"
results[i].size() == 4
and:
results[i][0] == name
results[i][1] == age
results[i][2] == title
results[i][3] == price
where:
i | name | age | title | price
0 | 'author #2' | 32 | "Book #1 from author #2" | 1000.0
1 | 'author #2' | 32 | "Book #2 from author #2" | 2000.0
2 | 'author #3' | 33 | "Book #1 from author #3" | 1000.0
3 | 'author #3' | 33 | "Book #2 from author #3" | 2000.0
}
}
view raw BookSpec.groovy hosted with ❤ by GitHub

Nessun commento: