You’ll notice some drywall dust around this blog today, all part of a renovation project that I’m just tentatively taking the wraps off now. After 10 years of maintaining this blog in a masking-tape and baling-wire codebase that started life as something called “the Catherine Hennessey engine,” I’m migrating everything to use the open source Drupal system,
To longtime readers this may come as a surprise. Certainly it’s surprising to me. Or at least to 1999 me. I’m a coder at heart, and the notion of using someone else’s code to maintain as something as intimately connected to me as my words was, for the longest time, anathema.
But for the last six months I’ve been knee-deep in Drupal, part of a large website migration project for one of our clients. I’ve been churning out custom Drupal modules, learning the ins and outs of “the Drupal way,” slurping content out of myriad ye olde CMS into Drupal and helping a team of editors and designers make Drupal their home.
Along the way I started to love Drupal. To love its quirky yet powerful undercarriage, its rich collection of modules, its open community of developers.
And in the end I realized that if I was going to be writing code, I might as well be writing code that could help more than just, well, me. There’s a lot to be said for drawing from and contributing to the open source well, and that well seems enough like home now that I’m comfortable with it as a place for my words.
In this spirit I’m migrating somewhat before the “okay, everything’s done” stage has been reached. You’ll see evidence of this from the very basic design of the site (I started with the very nice Basic theme and am working along from there; I’ll keep working), from some broken links here and there (although I’ve spent a lot of time trying to ensure that nothing breaks), and from some missing content (I haven’t yet brought over the 17,000 comments that have been written readers – coming soon).
Also in this spirit I’ll be writing a lot about some of the challenges I faced in migrating from the old homebrew system into Drupal.
In the meantime, some technical notes:
- the URL for the site’s RSS feed is now ruk.ca/rss.xml – but the old URL should automatically redirect.
- the rukapedia is, at least for the time being, over at wiki.ruk.ca – the content there might end up here eventually; still thinking about that.
- things like my Twitter feed in the sidebar wil return soon.
Lots more to come.
Regular comment-leavers in this space will recall that, for many years, I’ve employed a simple, easy-to-read mechanism as an “are you human?” test to help cut down on spam. A recent uptick in the amount of comment spam — and weird comment spam it was — has prompted me to switch to using reCAPTCHA, a similar mechanism that has three distinct advantages over the old system:
- It’s harder to design automated attacks for.
- It has an listen-to-audio-option, make it more accessible.
- When you use it, you’re helping to digitize books.
I’m particular fond of point number three. Apologies to those that find this new mechanism a barrier to commenting.
There’s an interesting conversation playing out among Dave Cormier, Rob Paterson and me over on Twitter about buying local food, and how easy it should be. Dave started things off with an insightful blog post about how difficult he found it to find local farm sources of food, something that later led him to create a website designed to help solve this problem.
A slice of the conversation today surrounded whether it should, in fact, be easier to find local food. Dave and Rob are of the “we need a website that makes it easy for farmers to communicate to customers when the food is ready” opinion, and I, in short, am not.
Here’s why.
Every Saturday for almost as long as [[Oliver]] has been alive we’ve been going to the [[Charlottetown Farmer’s Market]]. One of our mainstays at the market is Kim Dormaar’s smoked salmon. And in the winter and spring the stand beside Kim’s is Taylor’s Taters, selling potatoes, carrots and other root vegetables.
When we first started stopping by Kim’s for salmon Oliver was small enough that he was in a stroller or in my arms. Eventually he grew tall enough to stand on his own and one day Garth at Taylor’s Taters, seeing that Oliver wanted to be closer to the action, came over and cleared away a spot on his stand where Oliver could climb up and get eye-to-eye with Kim and the salmon.
That space has been there for Oliver ever since, and when it’s not you can rely on Garth to hurry around and clear away the potatoes or the carrots for Oliver. And when Garth and Peggy take the summer away from the market (to grow potatoes), the organic greens operation that takes their place has helpfully carried on the tradition.
Over the years, as this tradition cemented itself, and we’ve gotten to know Garth and Peggy a little more, we’ve started to buy potatoes and carrots and the occasional turnip from them (Garth, bless his heart, is prone to sticking a free bag of carrots in Oliver’s hands when I’m not looking). A few years ago Oliver started bringing them a Christmas card, and they returned the favour by always making sure he had a candy cane before leaving.
Earlier this year Garth told me that this would likely be his last year at the market, as he was putting the farm up for sale and not sowing a crop this season; later in the spring he told me, with a smile, that he’d decided to continue on for at least another year. And when I blogged that there was only a week left to get their potatoes before they left for the summer, Garth told me there was a minor rush of customers that week who told him they’re heard the word through that blog post.
Now I couldn’t tell you Garth’s birthday, or even, for that matter, where his farm is. I don’t know anything about his family, or how he got into farming, or how he grows potatoes. Island friendships take a long time to forge, and me and Garth are still in the early stages. But I can tell you that I unreservedly trust Garth and the food he produces. I know that when Garth is harvesting his crop this fall, somewhere in the back of his mind will be the thought that, among the thousands of other people, Oliver will be eating those potatoes for supper this winter.
It’s taken more than 5 years for us to get to that point, and I don’t think there’s anything we could have done to get to the place we are now any quicker: trust takes time.
I could tell you similar stories about Kim and his smoked salmon, about Brett and his coffee, about the smoothie guys, about Karin La Ronde and her iced tea, about Lori and John and their perogies: they are all an important and trusted part of our lives, and our relationships with them have taken time.
Surely this is exactly what’s at the heart of “eating locally,” isn’t it? Yes it’s partly about “food miles” and “carbon footprint” and bioregionalism, but at the heart of the matter is trust and trust isn’t something you can get from a website or a directory or a toll-free “where can I get local potatoes today” hotline. Trust takes a long time to simmer, needs to be fed from both sides, and is, in essence, the “product” that local farmers are selling.
I’m not saying a “who’s got the rutabagas this week?” directory wouldn’t be a useful, practical tool when you’re jonesin’ for a local rutabaga. But if we really want to live out the dream of buying locally, then it’s going to take a lot more than that, and a lot of what it’s going to take comes to simple analog friendships built out over many years. That’s hard, sometimes frustrating (especially when you’re newly arrived in the community and it seems like a private club of insiders), but ultimately it’s the one thing that the food-as-cheap-commodity folks can never compete with.
The second piece useful analysis to come from my bank statement parsing exercise (the first being how much I spend on coffee) is a graph showing where I spend my money. It’s not a complete picture of my finances because it doesn’t include expenses paid with my credit card, which includes a lot of things like household expenses at Canadian Tire and travel expenses. But it’s a start:
Building on the work I did earlier in the week to automate the download of credit union statements, I’ve now created code to parse those statements and dump the transactions into a MySQL database table.
The memberdirect-parsestatements.php code will ingest a directory full of MemberDirect electronic statements and insert a database record for each transaction. Once you have your transactions in a database, you can then do fun things like this:
SELECT date_format(date,"%Y-%m") AS yearmonth,sum(amount) AS total FROM transactions WHERE amount < 0 AND item = 'CASA MIA' GROUP BY yearmonth
that shows month-by-month spending at Casa Mia.
I’m not sure how much the electronic statement format varies from MemberDirect credit union to credit union, so the script may require tweaking if you’re not using it to parse Metro Credit Union statements.
Remember my promised credit union statement parsing code. Well, it’s coming soon. But in the meantime I’ve learned that since July 4, 2007 (my first visit) I’ve spent $1982.67 at Casa Mia on 179 separate visits for coffee and related items.
This is less than I spent on electricity ($3142.92) and property taxes ($4475.38) over this period, but more than I spent on telephone service ($1402.40), shampoo and sundries at Shoppers Drug Mart ($904.34), and water and sewer for our house ($783.53).
Here’s my Charlottetown restaurant spending breakdown for January 1, 2007 through May 31, 2009:
Casa Mia | $1982.67 |
Tai Chi Gardens | $1182.17 |
Interlude | $600.93 |
Urban Eatery | $578.63 |
Leonhard’s | $421.35 |
Seatreat | $341.57 |
Town & Country | $281.28 |
Formosa Tea House | $168.50 |
Just us Girls | $163.21 |
Cedars | $162.57 |
Timothy’s | $158.70 |
Café So Ban | $145.10 |
Downtown Deli | $109.20 |
Beanz | $83.85 |
Conclusion: I eat out a lot (I spend an average of $7 per day at Charlottetown restaurants). Is there a possible [[reboot]]-style action item here? At the very least, I’m well on my way to my “spend $2,000, get a free cup of coffee” plateau at Casa Mia!
The Alibi Lounge opened recently at 77 University Avenue in downtown Charlottetown, next to Cedars and across from the Atlantic Technology Centre. I had lunch there.
The Good
- Transformed interior: barely a hint of former life as failed Indian and Chinese restaurants.
- The music is the best restaurant music in Charlottetown: perfect volume, excellent mix.
- Friendly staff (although my jury is out on being called “darlin’ ” by someone younger than me).
- Thai chicken soup: tasty, hot, homemade.
The Bad
- Password-protected wifi (staff advice was to “use the open wifi from next door at Babas”).
- Club sandwich was run-of-the-mill; hint of tarragon elevated it, but the poorly-toasted bread took it back down. It wasn’t horrible, but it didn’t change my life or leave me wanting to have it again.
- The napkins are made of a silk-like fabric. Napkins should never by slipperly.
- Fortune cookies: they taste bad in Chinese restaurants, they taste bad here. I get the irony, but how about something that’s ironic and tasty?
At the end of the [[reboot]] conference this year I ended up walking to dinner with Christian Dalager and I mentioned that my “one actionable idea” contributed at the end of the conference was to create an RSS feed of my banking transactions.
As it turned out, I was talking to the right man: not only was Christian interested in this notion, but already had done work to parse his own Danish bank’s electronic data (in his case he had to screen-scrape, a considerably more ambitious task than I hoped to require).
My “bank” is actually a credit union, and my credit union uses the same MemberDirect web banking platform that many other Canadian credit unions do.
My first thought when approaching the task was to simply grab data in the handy comma-delimited ASCII file format that’s available under “Activity Format” on the “Account Activity Request” page of the site. Unfortunately the transaction data this provides only includes “metadata” — like the actual place I made a debit card payment, for example — for the current month’s transactions; before then it’s only dates and amounts. This would be fine if I wanted to start my data with the current month (I could just made sure I grabbed the data before it lost its metadata layer at the end of the month), but I want to go back in time as far as possible.
Fortunately there’s another option: MemberDirect now makes “Electronic Statements” available for download going back, in my case, to the start of 2007. While the statements are PDF files, and therefor require some additional parsing to grab transaction data, they are metadata-rich and thus the best candidate for my project.
Rather than going through the process of downloading the 29 PDF files currently available to me, I decided to write a script that would login to my MemberDirect account and grab all available statements automatically. Fortunately this proved to be quite easy: the MemberDirect authentication model simply accepts an HTTP POST with the username and password, and sends back a session cookie that can then be sent back for all future requests.
After some experimenting and parsing of the HTML that gets returned, I’ve come up with memberdirect-getstatements.php, a PHP script that uses cURL and the PHP Simple HTML DOM Parser to login, grab the index of available years, and then download all available PDF electronic statements.
This script isn’t for the faint of heart: you’ll need a PHP-equipped host with cURL (if you have a modern Mac you’ve already got both) and it’s possible that the script might need tweaking for credit unions that aren’t mine.
More information is (or shortly will be) available on this wiki page. Comments and experiences welcome.
My next step is to write a parser for the Electronic Statements that will allow me to do some basic “how much am I spending on coffee”-type data analysis.
Update: you can grab the statement parsing code here to extract transaction data from the electronic statements into a MySQL table.
8:25 a.m. - Arrive on Bus #1 at the University of PEI. Bus pulls right into the parking lot as it usually does.
10:03 a.m. - Ready to depart UPEI. See posters on bus shelter advising the the bus will not pull into parking lot as it usually does, but ignore these given 8:25 a.m. experience.
10:07 a.m. - See a bus drive by on University Avenue. Assume it was my bus and that posters are actually accurate. Phone Charlottetown Transit and seek confirmation; friendly operator puts me on hold, calls the bus that drove by and asks driver to come back and get me.
10:10 a.m. - Bus comes back to get me.
This is what it’s like to live in a small town with a customer service-driven transit company.