Friday, August 13, 2010

DBIx::Class join, prefetch

Over the last 15 years I've joined two database tables into a one-to-many relationship about a billion times. But I've never had any software let me loop the left table and right tables separately before. Turns out this magic has been in DBIx::Class for several years.

Runnable demo.

When table 'foo' is in a one-to-many relationship with table 'bar', you can:

my $foo_rs = $schema->resultset('Foo')->search(
join => 'bars',
prefetch => 'bars',
order_by => '',

while (my $foo = $foo_rs->next) {
printf "%s\n", $foo->id;
if (my $bar_rs = $foo->bars) {
while (my $bar = $bar_rs->next) {
printf " %s\n", $bar->desc;

Still one SQL statement against the database (fast!). Much prettier than ugly manual de-duping of redundant columns.

Saturday, August 7, 2010, you're my hero!

Holy crap! The people running this auction site must be making a fortune! is an auction site where you pay to bid. Each bid costs $0.60 and raises the bid price on the item by 1 penny. Items start at 1 penny. I'm watching the bids on a $1600 laptop climb from $50 up to $73 and beyond. A $1600 laptop for only $73? What a bargain, right? Yup, if everyone else would stop bidding and let you win. Hint: They won't.

It says right here that this item "recently sold for $422.59." Someone saved $1200! Good for them! In the process, raked in $25,355.40 (42,259 * $0.60) in fees on the sale of a single $1,600 laptop! HOLY CRAP!

Capitalism rules! I need to launch one of these sites and only charge $0.50 per bid!

Update: This ad says "Honda Civic Sold for $2,642!" There's another $158,520 in bidding fees for Also, for the company spin: Does QuiBids make excessive profit on their auctions? (Of course not! We have to pay rent and stuff! -grin-)

Wednesday, July 28, 2010

OS X "Address Book" sync fail to Google

I assumed this would all "just work" in 2010, but I guess I was wrong. My toys:

OS X 10.6.4 MacBook, OS X 10.6.4 Mac mini
Mail, Address Book, iCal
Mail + Contacts, Calendar
HTC Evo 4G (Android 2.1) mobile phone
Mail, People, Calendar
My email and calendar sync everywhere. Woot! OS X Address Book, however, completely fails to sync to Google. There's a checkbox in Preferences for "Synchronize with Google" that appears to work, but every time I quit Address Book and restart it, that box is no longer checked.

Apparently lots of people spend years fighting this stuff, or spend $100/year for Apple MobileMe. I prefer just giving up on Address Book, satisfied that almost everything Just Works.

Update: Sheesh. OK, so the sync does work even without MobileMe if you work your butt off every time. e.g.: (1) Change a contact in Address Book. (2) Open Preferences, check the "Sync with Google" checkbox (yes, you have to do this every time you open Address Book. Somehow it remembers your username and password though) (3) Right click the MobileMe sync in the top menu bar. "Sync now". (4) Log out of Google Mail. (5) Log back into Google Mail. Done -- your contact change is in Google.

Tuesday, June 8, 2010

Adventure in Serenia

I wonder if my parents or my brother remember me playing this classic in the basement in Livonia, Michigan on our IBM PCjr. I sure do. One of my earliest computery memories.

Tuesday, May 18, 2010


From: Jay Hannah
Sent: Tuesday, May 18, 2010 12:36 PM
To: Andria Hannah
Subject: movie

Oops, I forgot. Put 'Deadgirl' somewhere Zach won't find it. Not appropriate.



From: Andria Hannah
> Okay. Did mention to him on Sunday to watch the other movies
> we rented and that one was a flat out no from him. So we
> lucked out.

From: Jay Hannah
> I'm very disappointed in your judgment that you let ME watch it.
> My mother will be calling you.

From: Andria Hannah
> That bad huh? Was is scary?
> So to add to my “Do not let Jay do…..” list, I will include
> looking at the dollar shelf.

From: Jay Hannah
> Um, no it was... um...
> Let's just say I don't want Zach thinking about zombie sex
> slaves.
> waaaaaaaay off the "how to treat women" planet for any 13
> year old.
> Or 34 year old.

From: Andria Hannah
> Got it. Maybe that should be back in Family Videos
> “secret room”.

From: Jay Hannah
> Well, it's definitely not porn.
> It's just... um...
> Give it watch and you tell me what it is. :)
> In it's defense, the only guy that lives to the end is
> the only guy that doesn't use the dead girl as a sex
> slave... So I guess it should be in the romantic comedy
> section. :)

Thursday, May 13, 2010

Catalyst and Quality Assurance bliss

I've fallen in love with website testing. Again. Catalyst and WWW::Mechanize are awesome. The scenario below takes several monotonous and error prone minutes to QA as a human, or several seconds as a series of automated tests. New feature + test coverage == Joy!!

$work[0] test count is back over 3,000 again and Hudson is keeping an eye on everything for us every 30 minutes. Very cool.

$ perl -Ilib t/avail_book_SG-autoenroll_cancel.t
[debug] Statistics enabled
ok 1 - GET
ok 2 - Content-type:
ok 3 - title>
ok 4 - Select a City
ok 5 - No errors
ok 6 - !- BEGIN: om/rr/ -->
ok 7 - !- BEGIN: om/rr/ -->
ok 8 - !- BEGIN: om/rr/ -->
ok 9 - !- BEGIN: om/rr/ -->
ok 10 - Res ID(s) are 40002401426
ok 11 - SG number 62379458 created by sg_auto_enroll checkbox
ok 12 - click Activate Account Password & Preferences
ok 13 - !- BEGIN: om/sg/ -->
ok 14 - submit SI4 (form fields should have been defaulted for us)
ok 15 - !- BEGIN: om/sg/ -->
ok 16 - submit SI3
ok 17 - !- BEGIN: om/sg/ -->
ok 18 - GET /?Phoenix_state=clear&pagedst=RR2
ok 19 - !- BEGIN: om/rr/ --> Retrieved 40002401426 for cancellation
ok 20 - Click 'Cancel Reservation'
ok 21 - Reservation 40002401426 cancelled
$ cat t/avail_book_SG-autoenroll_cancel.t
use Test::WWW::Mechanize::Catalyst 'Phoenix';

use strict;
use Test::More tests => 21;
use FindBin qw($Bin);
use lib "$Bin/lib";
use phoenix_test;

my %SI3_args = (
loginName => ('jhannah' . time),
password => 't123',
EMAIL => '',
Question => 'CITY',
Answer => 'Shmomaha',

my $mech = Test::WWW::Mechanize::Catalyst->new;
my $pt = phoenix_test->new(mech => $mech);

my $cro_resno = $pt->book(sg_auto_enroll => 'on');
my $msg = qr/Your Select Guest number is (\d+)/;
my ($sgnum) = ($mech->content =~ $msg);
"SG number $sgnum created by sg_auto_enroll checkbox");

$msg = 'Activate Account Password & Preferences';
$mech->follow_link_ok({text => $msg},
"click $msg");

my $msg = '!- BEGIN: om/sg/ -->';
$mech->content_contains($msg, $msg);
"submit SI4 (form fields should have been defaulted for us)");

my $msg = '!- BEGIN: om/sg/ -->';
$mech->content_contains($msg, $msg);
with_fields => \%SI3_args,
}, "submit SI3");

my $msg = '!- BEGIN: om/sg/ -->';
$mech->content_contains($msg, $msg);