While I was working on the acts_as_resource
plugin trying to fix things up so that the resource finding side of things works neatly, I realised that I needed some way to get at the ordered list of parameter keys that were matched by the routing system.
One way to do it would have been to parse the path again, but that smacked a little too much of repetition, after all, the routing system knows this stuff already, but how to get at it?
So, you’ve upgraded to Rails 1.2.1 and you’re working on a tool to maintain a database of all the tunes you have in your various songbooks and (eventually) your record collection. You start with:
$ ./script/generate rspec_resource MusicBook title:string author_id:integer \
abstract:text
$ ./script/generate rspec_resource Tune title:string composer_id:integer \
abc:text book_id:integer
You decide to come back to composers and authors later, so you set up your models[1]:
MusicBook.has_many :tunes
Tune.belongs_to :music_book
Your mission, should you choose to accept it, is to explain what the following code does:
class Amb
def initialize
@error = Exception.new("Ran out of possibilities")
@failure_continuation = lambda {|v| @error}
end
def assert(assertion)
if !assertion
self.fail
end
end
def deny(assertion)
assert !assertion
end
def fail
@failure_continuation.call(nil)
end
def maybe
one_of [true, false]
end
def one_of(collection = [])
k_prev = @failure_continuation
callcc do |k_entry|
collection.each do |item|
callcc do |k_next|
@failure_continuation = lambda do |v|
@failure_continuation = k_prev
k_next.call(v)
end
k_entry.call(item)
end
end
result = k_prev.call(nil)
if result == @error
raise @error.message
end
end
end
def all_values(&a_block)
k_prev = @failure_continuation
results = []
callcc do |k_retry|
@failure_continuation = lambda {|v| k_retry.call(false)}
results << a_block.call
k_retry.call(true)
end && fail
@failure_continuation = k_prev
results
end
end
Easy? Now explain how it does it.I’ve been watching this five things meme coursing round the blogs I read for a while now, and chromatic just tagged me to share five little-known personal facts.
- In a perfect world I would be making a living as a folk singer. In the real world, the market for an unaccompanied singer of mostly traditional songs is somewhat limited. There are very few things in life enjoy more than singing in good company.
- I’m secretly very shy.
- Unless you were at that OSCON that time, you probably don’t know that I can make a icosidodecahedron out of modelling balloons. If anyone has worked out how to make a buckyball from balloons, I would be grateful for the pointer.
- I’m a compulsive gambler: it’s been years since I had a bet and more years still since I attended a Gamblers’ Anonymous meeting. I basically threw away thousands of pounds and any chance I had of a decent degree. I can’t say I’d recommend it.
- I am a tea snob. Not for me the Tetley’s teabag in a mug being doused with boiling water (but if must be bag tea, then Tetley’s is the one), oh no. In the afternoon it must be a pot made with loose leaf Earl Grey China Moon from Imperial Tea and Coffee of Lincoln in the morning, a pot of Superior English Breakfast from the same place. Tell ’em I sent you.
Tradition demands that I now tag 5 others to do the same thing, so I call on: Scott Laird, Jesse Vincent, Dave Cross, Andy Lester and Mary Branscombe to spill their beans.
A friend of mine, David Morton, just pointed me at a transcript of a lecture given by one Christopher Small. In it Small nails something I’ve been trying to articulate for ages. I don’t know whether to applaud madly or seethe with silent resentment that someone said it so much better, and in 1995 at that.
On balance, I’m applauding. Read it, it’s worth it for Opera story alone.
Cast an eye over my new venture. It’s pretty much a place holder site at the time being, but I’m beavering away at the bits that need beavering away at.
My dad drives a vintage Fraser Nash. I say drives, but that’s only half the battle, a large part of his Nash time is spent fettling it. It’s an old car; bits wear out, break or drop off. And because it’s an old car, you can’t just nip round to Halfords and pic up a replacement; nor can you head down to the breaker’s yard and cannibalize something else. So he has a lathe and a milling machine and a bewildering collection of tools. When he needs a part, he will disappear into the machine shop and, after sufficient swearing and/or bleeding, he will emerge with a newly made part. For dad, it’s all part of the fun of running a vintage car. If he weren’t able to do the work, the Nash would have had to remain a pleasant pipedream.
I’ve been eyeing the rspec and rspec on rails packages and thinking I should give them a go.
To my eye at least, something like:
context 'Given a published article' do
fixtures :contents
setup { @article = contents(:published\_article) }
specify 'changing content invalidates the cache' do
`article.body = 'new body'
`article.invalidates\_cache?.should\_be true
end
end
context 'Given an unpublished article' do
fixtures :contents
setup { @article = contents(:unpublished\_article) }
specify 'changing content keeps the cache' do
`article.body = 'new body'
`article.invalidates\_cache?.should\_be false
end
end
reads far more fluently than the equivalent Test::Unit based tests:
class CacheSupportTest < Test::Unit::TestCase
fixtures :contents
def test\_changing\_published\_article\_invalidates\_the\_cache
art = contents(:published\_article)
art.body = 'new body'
assert art.invalidates\_cache?
end
def test\_changing\_unpublished\_article\_keeps\_the\_cache
art = contents(:unpublished\_article)
art.body = 'new body'
assert ! art.invalidates\_cache?
end
end
So, I installed everything and started to work on a new class in Typo using rspec. Rather annoyingly, this seemed to break the current test suite, so instead of working on my new model class, I set to porting the existing suite.
And, on about my third test suite, I found what I think is a bug in the suite. I'm not *sure* it's a bug, because, the way the test is written (by me, I admit it), masks the intent quite dramatically. I'm also finding that the freedom to name specifications and contexts in English rather than `method_names_that_go_on_for_ever` is forcing me to come up with much more useful descriptions of what I'm testing. I find myself working on making the spec runner output read reasonably well as English, and doing that casts light on what is and isn't being tested.
I've known for a while that Typo's test suite is, um, spotty, but the porting process is really helping me get familiar with what's being tested. I'm half tempted to start adding extra specs as I go, and if I could work out how to keep the existing tests working while I did it, I would, but my priority for now is to get to the point where I can check the specs and be confident that the new specs are no worse than the old tests.
Because I'm much more confident that I know what the specs are *doing*, I'm also confident that it won't be hard to revisit them to help specify typo's behaviour better. I'll just have to give myself the discipline of beginning each coding session with half an hour of fleshing out the specifications before I get back to adding behaviour.
Why do people have to be human with my new computer?
You would think that arriving home and opening up a brown cardboard box and pulling out a shiny new 15" MacBook Pro 2.16GHz would be a fine thing wouldn’t you?
It’s rather less than fine when what you’d paid for was a 17" MacBook Pro 2.33GHz.
Annoyingly, it turns out that this wasn’t a case of someone in the local store pulling the wrong box from the stockroom. That would be easy to fix. Instead, it turns out that someone in Northampton had a moment of humanity and mislabeled the box - the stockroom monkeys in my local branch have apparently checked the apple labels of all the MacBooks in the shop to no avail.
Writing migrations can get pretty tedious when you’re being scrupulous about writing both the up and the down side of the migration. Okay, so the Textmate ninjas amongst you can use scarily clever snippets to populate the down
migration while you write the up
method, but I can’t be the only Mac user who still prefers Emacs. And not everyone gets to run on Macs either.
So, inspired by something Jamis Buck wrote about designing a DSL, I’ve been sketching out a DSL for describing the easy parts of a migration in declarative style. None of this is implemented yet, but I’m pretty sure that it’s relatively simple to implement for a decent Ruby metaprogrammer. I’m brain dumping it here so I can come back to it later, or, you never know, someone might have implemented it by the time I revisit…
Typo users with longish memories will recall the absolute disaster we had when Rails 1.1 shipped and Typo wasn’t even remotely compatible with it. Even edge Typo didn’t work with 1.1. Chaos and confusion, strong words from DHH, all manner of unfun things.
So, this time, we’re not going to let it happen. We hope.
For starters, the current Typo release, 4.0.3 is locked to Rails 1.1.6 - if you install it from the gem it will insist that you have an appropriate Rails gem installed too. If you install it from SVN, it will use the magic of svn:externals
to stick the right version of Rails in vendor/rails
and, if you’re using SVK, we assume you have enough of a clue to populate vendor/rails
appropriately.
I would love to be able to run a slideshow on a second screen based on a ’live’ album in Aperture. So, when I drop an image into an Aperture album on my primary screen, it shows up when appropriate in the secondary screen slideshow.
I can live with having to take an explicit ‘publish changes’ type step from within Aperture, but I’d rather not, and I certainly don’t want the secondary slideshow to stop.
Gill needs to go to Berlin next week to do some research at the university and the Ethnological Museum, and it’s no fun flying with a CPAP machine and an insulin pen in these paranoid times.
So I shall don my chauffeur’s hat and we’re taking the ferry from Hull to Rotterdam on Monday night and driving to Berlin. So, if anyone reading this has tips for places to see, restaurants to eat at and all that good stuff, I’d be delighted to hear from you.
Hmm… it’s been 3 months since I last did this. Time for another look at the incoming queries log.
You may or may not know that Typo is multiblog capable under its hood. There is a blogs
table in the database and every single request ends up fetching the blog object by doing a Blog.find_by_base_url
query.
We don’t have UI support for multiblogging though, and the vast majority of Typo installations have exactly one blog object. Even when multiblogging comes along, there won’t be that many blogs in any given installation.
I’ve been taking an accidental sabbatical from Typo. It started during conference season, then there was a bunch of housekeeping and general home type stuff that needed doing, so I’ve been away from the codeface for a while (and I still haven’t turned my EuroFOO talk into a podcast, or finished scanning and uploading all the EuroOSCON photos…)
However, I am back and coding, and a new typo feature just made it to the top of my todo list: This morning, in a fit of over enthusiasm, I managed to zap the 36 most recent comments on this blog. And, for bonus points, I didn’t have a backup.
I just pulled the the entry entitled It’s not just open source that has a problem with sexism. Here’s why:
My intention was to point up the kind of unthinking, ingrained sexism that is all too common in our field. My friends’ email exchanges with a conference organizer were textbook examples of the sort of thing I mean, so I used them and posted them pretty much verbatim without a thought. I was aware that it might cause offence, but my aim was to make the organizer stop and think about the message his conference website was sending out. So, basking in the knowledge that I Was Right, I pressed publish and was damned.
I stand by what I said in my last post. The fight against that kind of ingrained, unconscious sexism is one that is well worth fighting.
But this morning I read about a woman who is fighting to have her claim of asylum recognized so that she will never have to return to her home country where she will be obliged have her clitoris cut off. What’s really depressing about the story is that she’s had to take her appeal all the way to the House of Lords - apparently the Geneva Convention doesn’t require signatories to grant asylum to people who fear persecution on the grounds of their gender. Only “on account of race, religion, nationality, membership of a particular social group, or political opinion.”
Whatever your opinion the the Iraq war, whatever you think of Our Glorious Grinning Leader, it is still possible to point to at least one unqualified Good Law brought in by our current government.
<typo:lightbox img=“188231238” thumbsize=“small” displaysize=“large”/>
In July this year, my uncles, after being together for 36 years, got married. The law calls it a civil partnership, but it’s marriage in all but (official) name.
Yay! One Good Thing. Better than many governments manage I think.