Okay, maybe that’s an exaggeration, but I’ve been digging into Groovy in Action (GinA) and the Definitive Guide to Grails (DGG) more lately and keep finding nuggets that I apparently missed on my first few readings.

(I’m trying not to be annoyed about that, btw. By this stage in my career, I know all too well that I have to re-read things over and over to really “get” them. I just wish I retained more than I apparently do. I guess I’ll always think that.)

Anyway, recently I wrote a blog post about how I was able to iterate over Dates because Groovy treated them as a Range (yes, capital R). I thought that was really cool and wasn’t sure exactly why it worked.

Lo and behold, on page 96 of GinA, Listing 4.1 includes


def today = new Date()
def yesterday = today - 1
assert (yesterday..today).size() == 2

Page 98 points out that “any datatype can be used with ranges,” provided it implements next() and previous() and implements Comparable. This is equivalent to overriding ++, –, and the good ol’ spaceship operator, <=>.

(As a long-time Java developer, I have to say that any language that has a spaceship operator is inherently cool. Except Perl, of course. :))

I keep finding ways to rewrite my code as more idiomatic Groovy (or maybe I should just say, groovier). I used to calculate the number of days in a training course from the start and end dates using:


int days = 0
for (date in startDate..endDate) { days++ }

Now I realize that since a Range is an actual object, it’s simpler just to write:


int days = (startDate..endDate).size()

At least when I wrote the first version, I had a feeling I was making it too complicated.

Moving on to Grails, I wanted to have a “days” property on my Course class, but it’s a dependent property. Its value is determined by the existing startDate and endDate properties. That meant I didn’t want to add it as a formal property, because that would imply the existence of a setter method as well as a getter. Also, it doesn’t exist in the database and doesn’t need to.

I couldn’t find an appropriate annotation in DGG, but a quick question on the mailing list cleared it up. My class now looks something like


class Course {
  int id
  Date startDate
  Date endDate
  String title

  // associations, toString() override, and constraints as usual

  transients = ['days']
  int getDays() { return (startDate..endDate).size() }
}

By providing the getter, I don’t need the attribute, which is a normal JavaBeans convention. By putting the property in the transients closure, I’m telling Grails that it doesn’t have a corresponding column in the database.

Unfortunately, I found that when I tried using “days” as a property in in a GSP, sorting on it didn’t work. I think that’s because the tag actually generates a database query with an order by clause, and that’s going to be a problem with a property that doesn’t exist in the database.

I did realize I could compute my total number of training days in a one-liner:


Course.list()*.days.sum()

That uses the wicked cool spread operator, too. In my CourseStatistics class I don’t actually make that list query more than once, but it’s nice to know I could.

I’ve been using Groovy and Grails for about a year now, and it’s nice to know they’re starting to sink in. 🙂

One thought on “All I know I learned from GinA (and DGG)

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.