Ready for the world: ARegistryFor.Us

As many of our readers know, I built a registry website which we used for our wedding registry. The main reason for going through this hoopla was that there wasn't a good online wedding registry website that didn't also solicit the people visiting your registry for their email address. I found this to be unacceptable and thus created my own (harvesting emails to send ads to my friends and family is just not cool).

At the time, I had made the visitor-side look fairly nice and clean, but hadn't spent any time polishing up the user-side. I've been working on finishing this up since the middle of November and now things have come together pretty well. So, go ahead and take a look at the site: ARegistryFor.Us. But, bear in mind that I'm not a marketing goon, so the "marketing" material on the home page is probably pretty low-quality. If you've got suggestions, or are a marketing goon and would like to give me some tips, feel free.

Also, if you know anyone who's getting married and might be interested let them know of this option.

Oh, also, please let me know if it doesn't seem to display properly for you. I don't really have access to a bunch of different browsers and operating systems to test on.

O Albertbaum, O Albertbaum

Today was the day we added a Christmas tree to our living room. Needing an authentic experience I found a cut-your-own tree farm in Castro Valley. So after work we zipped on out there to get a tree before dark. With my trusty GPS we found the place without trouble, obtained a trusty saw, and drove off into the wilderness. This tree farm isn't like we have them back in Connecticut where you park and walk around the property with a little cart. It's more like property which is up against the Chabot Regional Park. So you drive along an access road to the various lots which go out a couple of miles down the road. We drove out towards the back and found some good size trees to look at. We got out to take a look around, but left the camera in the car, so we don't have any pictures until we got Albert back to the car. Yes, sometime between cutting it down and carrying it to the car Jess named our Christmas tree Albert.

Anyway, there was a bunch of trees and they were all incredibly well pruned and full. I don't think we would have, growing up, spent hours in the cold if our tree farms had trees like these. They all had almost perfect shapes. I was very impressed.

So, we picked out Albert which only took about 5 minutes, cut him down, and carried him to the car. We came prepared with a tarp to put down on the roof to help prevent scratching up the paint, and some rope.
DSCN4465
Jess was skeptical of my ability to secure the tree to the car properly. But I knew the secret of the tow anchor points (or whatever they're called).
DSCN4466 DSCN4467After some adjusting and tying and knotting and such we had things ready to go:
DSCN4469Albert enjoyed his last stint of freedom and gave us no trouble on the way back (which involved a rather roundabout path in order to avoid the highway, I didn't think 70 mph would be much fun with a non-baled tree strapped to the roof).

We got the tree home and into the tree stand. On Jess' insistence we are not allowed to decorate it until Saturday when we will decorate it and then watch The Muppet Christmas Carol.
DSCN4470I told Jess that I wasn't sure our tree trip would count since we could still feel our toes and fingers when we finished, and there wasn't 3 feet of snow, and no one was crying; but she claims that it will count anyway.

Grails: Querying across associations

Another nerdy post. Grails is a pretty good framework. I'm a python guy, so I prefer Django, but when forced to use Java-like things Grails is better than the alternative. However, it's still young. Django and Grails are both currently on their 1.1.1 releases, but Django is much more mature for its age.

In Django it's really easy to query across related objects (they're called "related objects" in Django and "associations" in Grails). Grails is still struggling with this. (Grails is also struggling with good, in-depth documentation, but that's not the purpose of this post.)

After much searching all I could find was some forum posts by the project lead of Grails, Graeme Rocher, from 2007 saying that nested associations aren't currently (as of 2007) supported.

Nested Associations: Suppose I have 3 classes: Person, Family, and Country. Suppose the classes are designed such that each person belongs to a family and each family is linked to an origin country. Now suppose you want to get a list of all persons whose family is from England. Persons don't have a direct link to that information, so you'd need to hop through the family to get to the country.

Based on the current setup you'd expect to be able to do something like:

Person.withCriteria {
family {
country {
eq("name", "England")
}
}
}

And you can. So for anyone searching for how to do this and finding that old post from 2007 saying you can't: it's wrong. You can.

But now let's pickup where I left off in my previous post with separating out query pieces for re-usability and adherence to the DRY principle.

We need to build a criteria object specifically and separate out the criteria to a separate closure:

def someView = {
def critBuilder = Person.createCriteria()
def critClosure = { filterByEngland.curry(critBuilder)() }
def results = critBuilder.list(max:params.max, offset:params.offset, critClosure)
def totalCount = results.totalCount
}

def filterByEngland = {critBuilder ->
critBuilder.family {
critBuilder.country {
eq("name", "England")
}
}
}

And now we can combine that with other pieces of modularized code. I have my queries broken up so that I can easy sort using different functions based on what kind of output the data is going to be used in. So you can have something like this:

def someView = {
def critBuilder = Person.createCriteria()
def critClosure = {
filterByEngland.curry(critBuilder)()
sortForCSV.curry(critBuilder)()
// sortForXML.curry(critBuilder)()
}
def results = critBuilder.list(max:params.max, offset:params.offset, critClosure)
def totalCount = results.totalCount
[results: results, totalCount: totalCount]
}

def filterByEngland = {critBuilder ->
critBuilder.family {
critBuilder.country {
eq("name", "England")
}
}
}

def sortForCSV = {critBuilder ->
critBuilder.order("lastName", "asc")
critBuilder.order("firstName", "asc")
critBuilder.order("age", "asc")
}

def sortForXML = {critBuilder ->
critBuilder.family {
critBuilder.country {
order("name", "asc")
}
order("id", "asc")
}
}


Since this nested association querying isn't documented anywhere (that I could find) and the only mention is that it _doesn't_ work, it was a pain in the butt figuring it out.

Other gripes with Grails. I can't define a relation to another class unless it is based on the primary_key of the classes. A less-than-usual case for sure, but there really isn't any good reason to disallow such a situation.

Life at Work

I've been working some small projects to prototype using Groovy and Grails as our new framework. It's been fun to focus on a small project with enough time to actually polish it up nicely. The Grails framework lets us actually focus on functionality rather than minutiae that make the system function. So we've been putting together a nice little system which uses Ajax to provide a quick and clean interface.

Halloween

Ok, we've been lazy about Halloween. Ok, Ok, blogging Halloween was _my_ job, so I've been lazy.

Anyway. The week before Halloween we went out to a farm in Lathrop which was supposed to have a pumpkin patch which would allow you to pick a pumpkin straight from the vine (unlike the "pumpkin patch" in Livermore which trucks them in and lines them up). So we headed out there for the pumpkin patch, and corn mazes, aand pumpkin CANNONS!

It turned out that the pumpkin was a bit lame. It looks like it had been an actual patch, but it looked like they had done their best to destroy any vines that had been there.

But we did still go through a corn maze:DSCN4427Jess didn't particularly enjoy the corn maze. She felt that if she wanted to be lost, she could just go walk around town for 10 minutes. After wandering for a bit we picked a wall and followed it all around until we got out. There were 3 mazes, but we only did one.

Then we headed over to the CANNONS! You get a bucket of small pumpkins that you can load one-at-a-time into your compressed-air cannon. It was getting dark and the lighting was crappy so the pictures aren't very good. In this one you can see one of the targets you get to aim at, a giant jack o' lantern. There was a good 6 feet of piled pumpkin remains at its base:DSCN4430And here's Jess:DSCN4433
So that was fun. The pumpkin cannons were definitely worth it.

We bought a pumpkin from the grocery store because it was cheaper than the "pumpkin patch". We didn't get around to carving it until Halloween. I began working on a top-secret pumpkin exo-skeleton project:DSCN4442It didn't work out very well. But the jack o' lantern was pretty decent:DSCN4444We sat about waiting for trick-or-treaters (with a big bowl of candy) but were rather disappointed in that regard. We had one family with 3 small kids come by. That was it. So now we have a bunch of candy to eat (and Jess got more for 75% off at CVS after Halloween). Since the door wasn't busy Dr. Horrible walked down to Panda Express for traditional Halloween cuisine (the new SweetFire Chicken Breast is awesome, I can't eat Orange Chicken anymore):DSCN4450