I blog when I go abroad, and occasionally when I do stuff in the UK too. There's a nicer interface over here.

Monday, September 29, 2008

A new type of django relationship: Generic Intermediaries

Bloody hell, it's a second technical post in the space of a week. I was really bored last night (when I wrote most of it, as the publish date suggests); had seen both of the Family Guy episodes on FX several times before, and similarly I've seen Die Hard enough times for it to not really require another viewing. Now, if it had been in HD... anyway, the upshot was that out came OmniGraffle, before I knew it I'd created a diagram and then, well, a picture needs a thousand words of explanation. So, after the lozenge, here they are.

NB this stuff is also included in the django-slots wiki; I thought it would be sensible to post it somewhere that might have an audience, as well as this blog.


Generic intermediaries: relationships with characteristics

Introduction

This document describes the GenericIntermediary django model and IntermediaryKey, a key-like object. Together these two classes provide a mechanism for giving characteristics to relationships between models.

Existing relationships in django

fixed relationships

Django already provides relationships between models. These allow you to link single or multiple instances of models to one another. Their existence is reflected in the database schema behind those models, be it generated when using syncdb or defined explicitly with dmigrations. I'm calling these relationships fixed because the model on either side of the relationship is explicitly specified in the code.

generic relationships

The content types application (django.contrib.contenttypes) ships with django and is in INSTALLED_APPS by default. As well as providing a unique identifier to all model instances in your project through an app/model/id triplet, you also get the ability to specify a generic foreign key and/or generic relation. This lets you genericise one side of a foreign key relationship: that is, specify that your model can be attached to any other model. This relationship is specified by using two fields: a ForeignKey to ContentType, and a regular field used to store the ID of an instance of that type. As with the fixed relationships, therefore, this requires columns in your schema, to reflect the fact that the model is related to something else.

Generic intermediaries

Generic intermediaries are a way of specifying that a relationship exists between two model types separately from the instances of those models. The relationship is then given characteristics through a new model, in which the fields containing the instance IDs are also stored. This model can then be used to create a mixin, a Manager-style object or Key-style object, to give new attributes to existing models without requiring schema changes. This is how django-slots is implemented.

Diagram

This is a diagram of how django-slots is implemented, including the slots_demo app which provides the Page and Style models.



Explanation

Page and Style are django models, implemented as normal, with whatever attributes they require.

Between them is GerenicIntermediary In concrete terms this is a model with just two attributes, each of them a ForeignKey on ContentType and a unique_together constraint ensuring only one relationship between two types -- in one direction -- can exist. The direction is important: as with the diagram, the two keys represent the models on the _left_ and _right_ hand side. The left-hand model is that which the right-hand types are _against_; in django-slots therefore Page is on the left.

Slot is a django model which has a ForeignKey on GenericIntermediary This is, in effect, a declaration that Slot implements characteristics of a relationship. Missing from the diagram (bolded to remind the author to remedy this!) are the attributes which contain the IDs of the instances which are related, that is, the ID of the Page objects and that of the Style objects.

Left at this, scheduling would be possible. You would create a slot like this:


# assume we have Page and Style objects called page
# and style respectively; we also have two datetime
# objects, start_time and end_time
cp = ContentType.objects.get_for_model(Page)
cs = ContentType.objects.get_for_model(Style)
gi = GenericIntermediary.objects.get(left=cp, right=cs)
slot = Slot(relationship=gi, against_object_id = page.id,
slotted_object_id = style.id,
start_time = start_time, end_time = end_time)


and retrieve it so:


# same assumptions as above; also same cp, cs,
# and gi assignments
now = datetime.datetime.now()
# look for a slot that now falls inside,
# against our page
try:
current_style_slot = Slot.objects.get(
relationship=gi, start_time__gte=now,
end_time__lte=now,
against_object_id = page.id)
except Slot.DoesNotExist:
current_style_slot = None
else:
current_style = cs.get_object_for_this_type(
id=current_style_slot.slotted_object_id)


This is horribly verbose and inconvenient. It's also not required.

Intermediary keys

Also missing from the diagram above is IntermediaryKey. As the name suggests this is a key-like object which relates to the GenericIntermediary. Informed heavily by the GenericForeignKey API, IntermediaryKey works by specifying which two fields together point to the instances on either side of the relationship. The first argument denotes both the relationship field (the foreign key on GenericIntermediary) and the side of the relationship, using normal django key__attr syntax; attr will always be one of left or right.

By having an IntermediaryKey the model gets an attribute which, like the fixed relationships, returns the actual instance of the related model.

This is how Slot uses IntermediaryKey


against = IntermediaryKey('relationship__left',
'against_object_id')
slotted = IntermediaryKey('relationship__right',
'slotted_object_id')


all this really gives us is the ability to use .against and .slotted as shortcuts to the instances of Page and Style in a relationship. The only improvement we can make to the previous examples is to shorten the current_style assignment:


current_style = current_style_slot.slotted


Still horrible, though.

Usage by django-slots

All the verbosity can be reduced (to taste) by the implementation of a class to define characteristics of the relationships, and the use of techniques to attach these classes to existing models.

django-slots' Slot model/class is the first such relationship (because GenericIntermediary and IntermediaryKey were invented for this project!); ScheduleMixin is the technique which attaches them to existing models.

The introductory blog post explains at a high-level what this means, in that it shows the API of django-slots. To fully understand the way to get from the above code to provision of attributes and methods, read up on mixin classes and see ScheduleMixin in models.py

Conclusion

GenericIntermediary and IntermediaryKey are not replacements for fixed relationships, nor generic relationships. Instead they are a way of representing the fact that a relationship exists between two arbitrary classes separately from the instances of those classes in the relationship. This is useful where:

  • the relationship between two models has characteristics itself;
  • one model's relationship with another is not, or need not be, an attribute of either;
  • a model wants to declare which other models are related to it, rather than the other way round; or
  • there is a need for another model to key on your own, when you cannot change its schema (eg in 3rd party apps you don't want to fork)

The mixin technique currently employed by django-slots demonstrates the first three of these use cases:

  • the relationship exists between two times
  • Style and Page are separate models with no explicit fixed relationships
  • Page declares that it would like Style to be attached to it; Style does not declare itself as tied to Page -- or anything at all

other random thoughts

I don't believe time is the only characteristic that could use this technique, which is why I've written such verbose documentation. I'm struggling to come up with proper use cases for, say, geographic foreign keys (where instead of start_time and end_time you might declare a bounding box, or latlong + radius?), but I have a gut feeling it could be useful.

Friday, September 26, 2008

alice


alice
Originally uploaded by Darren Foreman
After being sent a youtube clip of a stealth ninja cat this afternoon I was searching for evidence that Ruth's cats aren't evil. That made me look at my own photos of them, and find this one, which I just feel like flagging up here as my absolute favourite. Awwww.

Tuesday, September 23, 2008

Introducing django-slots

Sigh. Was it inevitable? I don't think it was, but it's happened anyway: I'm putting a purely technical post on my blog. Sorry and all that. Those of you who couldn't give a toss about python, django, coding, my job, and so forth can turn away now. Normal lack of service will resume shortly.

django-slots

This post introduces django-slots, a system for scheduling relationships between django models. It's an open-source (head-above-parapet) project which allows django developers to include time-based foreign keys in their applications/projects.

At the time of writing django-slots should be considered pretty nascent. Some reasons for this are detailed near the end. Nonetheless I believe even its current state provides enough useful functionality to justify its release.

Background and rationale

The first iteration of django-slots was a weekend pet project of mine, inspired by two things. Firstly, the team to which I belong at work were busy implementing several different solutions to what I considered a single problem: making a relationship between two objects occur for a period of time. Secondly, I believe that as a software engineer my job is to make my job easier; and as a software engineer on a CMS this mostly means that my job is to make everyone else's job easier too. This comes down to two things:
  1. Engineers should not be required to make changes happen at a particular time (and this means doing deployments etc).
  2. Users should not be using my software at times when I could really do without them calling me up saying it's broken (ie weekends, midnight, etc)
Both problems are solved by writing software which allows the future state of the data in my CMS to be scheduled, and previewed, in advance.

What django-slots is not

  • django-slots is not a system for making things appear and disappear, or exist and not exist
  • django-slots is not a tool to explicitly make something happen. It is not a replacement or wrapper for cron; nothing is ever triggered.
  • django-slots is not a replacement for foreign keys, or other normal relationships between entities
  • django-slots is not perfect or finished. By a long way.

What django-slots is

django-slots aims to provide developers with a way to satisfy the generic requirement of scheduling changes to relationships, designed with websites in mind. The most common concrete and specific example is probably to schedule a particular ad/sponsor/promotion to appear on a site between two times.

django-slots allows developers the freedom to define what "something" is through an intermediary mechanism. Unlike a normal ForeignKey, a relationship between two models exists separately from the instances of those models; the instance-instance relationship is bound to a period of time, known as a slot.

With this approach django-slots also provides a platform on which developers can build other tools to report, audit, preview, and more. A timeline of relationships means you can see the state of your data in the past, present, and future.

Furthermore, django-slots decouples models from one another, allowing them to exist and develop independently. No changes are required to the models which are scheduled, and no schema changes are involved in declaring the schedules attribute. django-slots is designed to be simple.

Finally, the mechanisms in use to implement the relationships inside django-slots are available for use by other applications. Specifically this means the definition of generic relationships between arbitrary model types on both sides (as opposed to the one-sided relationship already possible with GenericForeignKey). Where django-slots is concerned only with time, I envisage other applications in areas where similar concepts (universally identifiable points, etc) apply, eg geography.

Code

django-slots is hosted on Google Code, and there is a minimal installation guide on the wiki system which it provides.

http://code.google.com/p/django-slots/wiki/QuickstartGuide

Description

django-slots is used by telling your models to use a provided mixin class, and declaring a schedules attribute. This attribute should be a tuple of other class objects, which must be other django models.

By setting up your model like this you are declaring that a relationship can exist between it and those in the tuple. Your model is extended with properties and methods for querying and managing instances of these relationships. You can then schedule a relationship to exist, retrieve the current relationship or that for a given time, and retrieve a timeline of all relationships between your instance and instances of the other models.

API/usage


# models.py
from django.db import models
from slots import ScheduleMixin

class Style(models.Model):
# define your style model here
...

class Page(ScheduleMixin, models.Model):
# Style is the foreign key which varies according to time.
# NB. you don't need a default it it makes no sense to have one
...
default_style = models.ForeignKey(Style)
schedules = (Style,)

# views.py
def detail(request,...):
page = Page.objects.all()[0]
# the Style scheduled for right now, if there is one
style = page.current_for_model('Style')
if style is None:
style = page.default_style
# do stuff with style
...

# properties
# dictionary of schedules keyed by model,
# each entry is an array of slots ordered by time
page.schedule
# dictionary of all objects (or None) currently
# scheduled, keyed by model name.
page.current
# returns next scheduled objects (ie, where start time is
# later than right now) in same format as current
page.next
# returns last scheduled objects (ie, where end time is
# earlier than right now) in same format as current
# per-type query methods
page.last
# just the array of slots for Style
page.schedule_for_model('Style')
# the Style object currently scheduled, or None
page.current_for_model('Style')
# the Style object scheduled next, or None
page.next_for_model('Style')
# the Style object which most recently finished, or None
page.last_for_model('Style')
# finding what's scheduled at a particular time.
# NB this only works on a per-relationship basis;
# you cannot pass a datetime object to page.current()
page.current_for_model('Style',jan_1st)
# scheduling an object
page.add_to_schedule(style_object, start_datetime, end_datetime,
notes)
# a signal catches this and deletes all relevant slots
style_object.delete()

What's missing

As mentioned above django-slots is by no means complete. To my mind there are a few fairly crucial missing pieces right now:
  1. Removal (descheduling) of individual slots
  2. An admin interface.
  3. A test suite.
And there are bound to be far, far more. Hopefully such holes will be filled; better yet, hopefully others will (help) fill them.

Colophon

django-slots should work in any out of the box django installation, though it was written alongside django 1.0. The only configuration requirement is that django.contrib.contenttypes is in INSTALLED_APPS (this is the default).

Sunday, September 14, 2008

men and boats


Haven't confirmed whether or not it really was a race, but in the course of trying to put decent titles etc on the flickr set about the walk described in the previous post I have stumbled across this: Hampton Court Model Yacht Club.

Oh wow. I don't know what to make of that at all. The idea, the web "design", the any of it.

blimey, a walk

After getting a prod on twitter I managed to do today what I've failed to do so many times this year, and drag my sorry carcass away from the TV/xbox/laptop on a Sunday to go for a walk. Turned out to be a very good idea 'n all, for a number of reasons.

Not that I hadn't spent a bunch of time in front of the TV, xbox, and laptop this morning anyway. Got up with a vaguely woolly head and did a bit of coding unrelated to work, a habit I've surprisingly fallen back into after a 4+ year hiatus. More of that later, possibly; I'm undecided whether to ever launch or publish anything, the main motivation is just to learn how to do python well so I can do my job better.

Aaaaanyway. Coding on hold I put the xbox on to play Death Magnetic a bit more (what an album!) but left meself on Yahoo! Messenger so I could chat to the still-in-Pakistan missus when she popped up. Pop up she did, apparently with a very bad hangover, and she soon went back to bed after not much more than a quick hello. After that the twitter prod happened so I showered, sorted my GPS and camera (k850 in flight mode! hah) out, put a spare shirt in me bag and buggered off towards the Thames, destination Richmond.

I didn't go to Richmond. I did this:

Surbiton, Kingston, Home Park, Thames Ditton at EveryTrail

Map created by EveryTrail:GPS Geotagging

Hmm. That's not a bad embeddable widget (the other one everytrail do is worse). Anyway, I took the familiar route from home to Kingston Bridge, which on a day like today always reminds me, as if I need reminding, why I love living here. It's just such a nice view and walk. But I wasn't really hanging around to savour it, this was a very workmanlike trip, done to take advantage of the nice weather as an opportunity to do something vaguely healthy. I had my mp3 player on very loud, a bag on my back to both make sure my posture was OK and to provide some extra weight (the dual aim being to get some upper body benefit as well as lower body, and to just generally use up a few more calories than normal), and I was keeping up a pace that meant after just a mile or so I could feel me shins saying hello.

Mind you, it would have been really stupid to be out and not take any photos at all. I took some duplicates (ie, I've done this bit quite a lot) around the river and at Kingston Bridge -- including a pretty poor panoramic effort -- before diverting off a familiar track and into Home Park (which seems to also be called Hampton Court Park).

Oh, wait, I already skipped over the whole didn't-go-to-Richmond thing. Yeah. I got to Kingston Bridge and decided it was a daft idea. For one, I don't actually like Richmond. I do like locks, which means Teddington Lock would have been good, but I fairly recently walked with Ruth to Richmond Park which involved trekking as far as Ham along the river. But even with the spare shirt (designed to change into at my destination, out of the super-sweaty one I'd be in at that point) I didn't relish the idea of finishing up that far away and having to get a couple of buses back. Also I was sort of time-bound, in that I wanted to get back in time for QPR vs Southampton (4-1! Come on!) on the box at 4pm. So, all those factors combined to make me decided on a new route: from Kingston bridge, back on the other side to Hampton Court and then a train to Surbiton and home.

Turns out I went to Richmond, though, sort of. On the north side of Kingston Bridge there's a sign saying "Welcome to Richmond Upon Thames". Sure, it's only the borough, but, meh... along the river towards Hampton Court I spotted a sign which piqued my interest (the royals are going to kill a bunch of animals), discovering in the process of photographing it that I was next to a gate into Home Park that I hadn't previously known about. I knew there was a golf course there, and that in that area there was also a park, but I didn't know there were a few public entrances. Having stumbled upon that one I diverted my route.

Christ, was I ever glad I did. Not that I don't like walking that stretch of the Thames, but I've done it a few times and new things are always better than old. Better still, there were mushrooms and deer! The 'shrooms were pretty cool, but the deer took me by surprise, almost literally. I first spotted a few wandering around the car park of Hampton Court golf course, and then there were 3 just sitting on either side of the path I was walking along. Being a huge wouss I avoided walking between them, but did use poor digital zoom to get a snap of them once I was a safe distance beyond.

Home Park does actually seem to mostly be a golf course. It's quite boring. Oh, but before the deer I had gone past a lake where loads of blokes were, I think, racing radio controlled yachts. They were certainly using them, and a little portable tannoy thing was counting down 60 seconds until the start of something. I didn't hang around to see what it was.

Jubilee Gate was quite useful because it gave me a you-are-here moment, and showed me I was on the right path to one of the exit/entrances which is right near Hampton Court -- and that I could still avoid walking alongside the river. After crossing a couple of fairways I headed up a big corridor of trees towards a fairly majestic gate with the palace behind it. The gate was shut. It's shut from April 1st to the end of September. Toss. But it said I could go to ... Jubilee Gate, and walk along the river, to get to the Palace. Ah well. I hadn't actually expected to find a gate directly into the Palace gardens there, and am glad I haven't been there by myself since Ruth wants to take me there anyway. But it did annoy me that I had to backtrack.

If any of the above is interesting that's quite a surprise, and it's also quite sad, because that's about it. The rest of the walk was, obviously, along the river to Hampton Court bridge, then an ice cream before changing my mind (again) about the train and treading the roads through Thames Ditton and back home. Really nothing special, and that's why the pictures end as well. Still, 9.2 miles at 3.4 miles an hour is decent, in fact my brother had suggested I try to do a round 10 miles in 3 hours and that's the pace I managed, if not quite the distance.

Back home in plenty of time for the game. Got a call from Ruth telling me it wasn't and isn't a hangover; she's proper ill. :-(

Thursday, September 11, 2008

Blogging about things which aren't travelling is hard

Hard enough that I don't think I can be bothered with it. I did vaguely think about posting some reviews of all the books I've read recently but tbh I think I'd rather do that using @oo5 on twitter.

Clearly, in order to keep this blog going, I need to go travelling somewhere. Alternatively I could post something about scheduling arbitrary models against one another in django, but I'm not a tech blogger and don't really intend to turn into one.

Thursday, September 04, 2008

Crathes Castle


Crathes Castle

Crathes Castle
originally uploaded by Darren Foreman

Tuesday was easy. We had it all planned out. Go see a castle, come back, go walking, eat.

After a breakfast -- comprised of cereal, then scrambled eggs on toast cooked by the German Apprentice (still learning English, but apparently understood enough to know what 'salmonella' meant, judging by the instruction from the kitchen we could overhear) -- we went back to the bus station to get our transport to Crathes Castle. About 2/3rds of the way back towards Aberdeen, this castle had two distinct advantages: it was supposed to be really good, and the bus stopped right at the gate to the grounds.

Brushing aside the incomprehensible footwear compliments I received from an alighting passenger, we boarded and, as far as the driver was concerned, Ruth asked for two returns to Crathie [mumble]. Crathie is a village in the opposite direction, which the bus does indeed go through. After some confusion while the driver figured out that he wasn't driving towards Crathie, I realised the error and said "Crathes". Mix-up cleared up, the driver then sold us a ticket which doesn't exist -- a pass that would let us travel all over the place on that route, and other Stagecoach services. The exact kind of ticket we'd asked about on Monday at Aberdeen bus station and had been told doesn't fucking exist. In fact this was a better ticket -- cheaper than two individual passes, he sold us a family ticket that costs 19 quid for two adults and up to 2 children. Zero is, after all, "up to 2".

Crathes was great. It's the ancestral home of the Burnett family, and beyond that I don't have much to say about it that wouldn't just be a rubbish description of the pictures I took. That said I do of course need to boast about having seen and photographed a real live red squirrel. :-D Upon my return to London, and mostly as a result for having twittered about it, I learnt that this was actually something people were jealous of. Coo!

Actually, one notable thing which you won't find by reading up on the history of Crathes elsewhere is the sales technique of the woman in the ticket office and merchandise shop. We just wanted day tickets, but she virtually imprisoned us in her attempt to get us to join the National Trust. Despite our perfectly reasonable, logical, and sensible objections, she nonetheless kept insisting that we should pay the 50-odd quid fee to get a year's free entry to, and apparently of even more use, free car parking at NT properties.

We have no car, and Ruth is spending 10 of the following 12 weeks out of the country. Even when we said this, and promised to join the Trust upon her return -- so that we got a full year's benefit of our membership, of course -- she still insisted that joining NOW NOW NOW was the best thing we could do. Her basis for this argument was some utter nonsense about winter being a shit time anyway, and buying it now we'd already have our membership ready for when the weather starts clearing up.

That woman was fucking mad. We managed to pay just for day tickets, and escaped. As I said, the castle was great, and the gardens were too.

Back at the gate for the bus, we found ourselves unfortunately in the midst of the 2 hours where there are no buses to Ballater. So instead we had to go to Banchory, a fairly nondescript town about halfway between Aberdeen and our real destination. Had a pint, went in WH Smiths, got the next bus. It was a pikey shitty bus only really suitable for journeys of, say, 600 yards, rather than 20-odd miles. Cramped, uncomfortable, it was the first long road trip of the whole holiday that made Ruth feel ill :-( plus any chance of walking had disappeared. Ah well.

Back at the B&B we needed to get changed and find somewhere to eat. What with Tuesday not being Monday we'd envisaged having our pick of the restaurants in Ballater; and being Ruth's birthday she wasn't to pay a single penny towards it. The only thing required was that she needed to pick and book the place, since I hate using the phone.

She phoned every restaurant in Ballater, including the hotel bar at the Hilton Craigendarroch (oh how I wish we'd known about that place earlier! think of the loyalty points, the room upgrade, ... sigh), and found nothing. Zip. Nada. FUCK. ALL. Every restaruant in Ballater was full, apparently, and we had to go further afield. Specifically we found a table at a place in Aboyne, probably the nearest village once again back in the direction of Aberdeen. Called the Candlestick Maker, it was virtually empty and we learnt it was shutting within the next month. In fact the day we were there was the last Tuesday they were opening at all, as for some reason that was the weekday they were taking off in their last month. Who knows why?

As it happens the food and service were both spot on. Shame. I guess if Ballater's food really is that good then they just couldn't deal with the competition...

The bus timetable was very kind to us, either side of the meal. It dropped us off 10 minutes before our booking, and picked us up 10 miutes after we left. Who needs cabs? Even the local scrotes weren't particularly scrotal.



I did think I'd blog about Wednesday separately, but to be frank I can't be bothered. There wasn't much to it: bus to Aberdeen, lunch, train to Dyce, cab to the airport, couple of hours in the lounge, flight to T5, bus home, hello cats, hello Wooj.

Wednesday, September 03, 2008

turn that wine back into water


Ballater from on-high
Originally uploaded by Darren Foreman.
We checked into our B&B properly after lunch, a bit surprised to find we essentially had an entire wing to ourselves. Certainly an entire floor, they said "your room is upstairs" and it, our toilet, and our shower room, were the only things that were. And after tourist information had asked for a double room, which by the sounds of the phone call was likely to be a twin room turned into a double, the presence of a bunk bed was an eyebrow-raiser.

Thankfully there was a double bed as well. The bedroom was the full depth of building, giving us a view above the caravan park to the hills beyond at one end, and to Craigendarroch over the local housing at the other. The latter window was slightly worrying as it had no curtains, yet also the most scope for being spied on(!)

Also worrying, to us big city types surrounded on a daily basis by the scrotes of Broken Britain, was the knowledge that the front door was never locked and being asked if we wanted a key to our room. Such things are apparently not required in sleepy Ballater, and we felt almost guilty for saying we would like one. It reminded me of my bag quandary in Auckland the other year.

Anyway, the weather was gorgeous and the day was still young. On came the walking boots, out came the GPS and camera, and off we went. In Ballater tourist information we'd snagged a leaflet of local walks and decided to combine two of them: first walk along the river Dee until it met the one which went up Craigendarroch, the big fucking hill. So we started out through the caravan park, past the golf course, through a car park, and up to a church. Except it wasn't a church, it was an ex-church that's now a "restaurant with rooms" called The Auld Kirk.

At this point we actually had no accomodation for the following night (Tuesday). When booking in Aberdeen we'd deliberately given ourself an extra bit of freedom, although I'd tried pretty hard to convince Ruth that staying 2 nights in the same place would give us freedom, as we wouldn't have to check out and find somewhere that day. And I'd succeeded :-) but this place tested that, because it looked like a fucking cool place to stay. But we didn't, deciding instead to explicitly look in advance for opportunities to stay in a converted church on some future holiday.

The Auld Kirk was also the place where the two walking routes joined, so we left the first and joined the second. The trek up the hill is graded DIFFICULT but unlike another one of the same grade, it did not (apparently) require a high level of fitness or proper hill walking equipment. Good job, as I have neither.

Not really sure how far up we were when we turned back. It wasn't all the way, and from some angles it looked quite near the top... but from others it didn't at all. Either way it was a decent walk, got the heart going and the sweat beading, and was exactly the sort of things we'd had in mind for this holiday.



The Auld Kirk
Originally uploaded by Darren Foreman.
We headed back down the hill -- and it was probably a good idea we'd given up, as it started to rain. The descent would have been a bit more slippery and dangerous if we'd not. Back to the Auld Kirk where we waited for about 2 minutes for a waitress to come out, then we gave up and went to a pub in the centre instead. Beer and quiz/bingo machine session later we went back to the B&B. We ran into the landlord who was so happy about our request to stay a second night he did a little dance(!), and he'd just sorted out a curtain on the rear window too. Mint. In the room we happened to catch a good BBC show about learning magic tricks and stuff. Can't remember what it was called or I'd use the name and link to it.

It was only about 6pm. It would have been a shame to waste the great weather and countryside, so we actually went out for another walk. Cambus O'May had been on a signpost in a picture in the Aberdeenshire brochure we'd gone through back in the Aberdeen hotel, partially responsible for convincing us we could head inland for a better time. It's a few kilometres from Ballater along a walking track which traces the old train line, and it was that we headed along, finding its start point after a wander through the local housing estate.

Ice cream van music still in our ears, we wandered for a while, stopping at one point for a chat with a local dog owner whose Collie dog apparently loved rounding up sheep... just so long as it was on its own terms. It hated being told what to do. Daft thing, does it think it's a cat or summat? ;-)

We didn't bother going all the way to CoM though. It was getting nippy, we were getting hungry; we got as far as a decent view of a little castle-turret shaped house and turned back.

This whole Deeside area had done a very good job of reminding me of Tasmania, but I couldn't quite figure out why. It hit me on the way back into Ballater that the reason was fucking obvious: probably more than half of the towns and villages in the state were essentially Scottish, built on very similar lines in very similar countryside. A further similarity was soon evident as we struggled to find somewhere to eat. It was a Monday, and most of the restaurants were fucking shut.

In the end we had a meal in another hotel, which was piping through a fucking terrible local line-dancing AM radio station which interspersed the songs with ads the likes of which I thought had died out in the 80s. The best song by far was Turn The Wine Back Into Water, a Christian country lament from a guy imploring that God sorts out his addiction to grog. Nothing like taking responsibilty for your own actions, eh. I've since discovered, in the course of writing this, that it's by a bloke called T Graham Brown. Now that's a website.

Despite the awful music and terrible decor, the food and service weren't that bad really. Shame we had to tell about 4 different members of staff that no, we weren't staying there (and we never will!).

On Tuesday we were going to do one of the things you pretty much have to do, given how many there are in the local area: go see a castle.

Monday, September 01, 2008

the Dee after tomorrow

the Dee
the Dee,
originally uploaded by Darren Foreman.
It's a bit sad when I make a pun that doesn't actually make any sense, but, meh. I have totally lost my decent-title-writing mojo (if indeed I ever had such a thing). Anyway, about last Monday...

After a considerably calmer breakfast than Sunday (which was a fucking awful zoo-like experience), we checked out from the hotel and headed, via a Diet Coke purchase, to Aberdeen bus station. Everywhere was pretty busy because unlike in England on the same day, it wasn't a public holiday. The buses into Deeside run every 20 minutes, but not the whole way -- the service to Ballater is only hourly.

We'd given ourselves 20 minutes or so to buy a ticket, having researched the night before that a Bluebird Explorer would sort us out. It was only about 0930, and our plan was this: get the bus to Ballater (just under 2 hours), see if the B&B would take our bags, then double back and go to Crathes Castle. Back to Ballater in the afternoon and check in properly, explore, etc.

This plan failed. Immediately. First, we were in the queue for tickets until after 0945, thanks to there being only one person selling them and a couple of very awkward customers ahead of us. When we finally got to the front of the queue the woman said there was no pass she could sell us, and that our best bet was just to buy two singles to Ballater. Oh well. Two singles to Ballater then please...oh. You buy them on the bus. So we queued, and missed the bus, for nothing. Thanks a bunch, Aberdeen bus station! We spent a couple of minutes cursing our lack of foresight -- with hindsight, if we'd come to the bus station the day before, just after booking our B&B, we'd have found this out and not missed the 0945. Bollocks.

... time passes ... Diet Coke ... T3 magazine (load of shite that is) ...

Got the 1045 bus, paying £15 each for period returns to Ballater. It was £12 for a single, and we thought the extra 3 quid was worth it so we could come back on Wednesday, if we wanted (at this point I favoured a cab to the airport).

It fucking tipped it down while we were on the bus. Really bad weather. Things weren't looking good...until we got to Ballater. Off the bus, the sun was out, storm passed. With hindsight, our lack of foresight had turned into a blessing -- if we'd got that 0945 we'd have been utterly pissed on.

Ballater landscape
originally uploaded by Darren Foreman.

When booking the B&B we had discussed with the staff at the tourist information centre that we were using public transport, so they explicitly said they'd book us into somewhere in the centre of Ballater. So, a not-as-short-as-expected walk ensued -- past 2 hotels and a few more B&Bs, next to the caravan park on the edge of town, there we go.

Even after our delay and the walk it was still a bit bloody early, but the people at the B&B were super-friendly and took our bags in, letting us go free, even giving us a recommendation for lunch venue.

Wandering slowly to take in the views all around us, we strolled back to where the bus dropped us off and beyond and found the venue. It was a restaurant in the building where Ballater's own tourist information is; it looked busy, so we went in next door for leaflets instead, and ended up paying a quid to visit the Royal Train Station exhibit/reconstruction. There used to be a train line which terminated in Ballater, for Balmoral castle which is only a couple of miles away. It was built for Queen Victoria and was in use right up to the 1960s, though most of the exhibit is set in the 1800s. There's a replica super-posh-opulent carriage, and some interesting titbits of information. For example, her maj back then didn't trust the accordion-style things which join carriages (and were very very new back then), so instead made the whole train -- which was up to 800ft in length -- stop, whenever she wanted to move to a carriage other than her own. Now that's posh.

By now we were really quite hungry so went for lunch in another restaurant (website fucked at the time of writing), where I had the phenomenally Scottish combo of haggis to eat, Irn Bru to drink. Christ I love haggis, but even I had a bit of a struggle with the quantity they served. Conversation focused mainly on an angry, anti-Royalist Ruth getting constantly pseudo-riled by my consistent and persistent devil's advocacy. Heh.

Lunch over, it was back to the B&B to check-in properly. First impressions of Ballater were, frankly, fucking great.