I've been furiously porting my Ramaze CRUD helper from DataMapper to ActiveRecord and I've been quite surprised to find that it's only taken a couple of hours. I should hastily point out for non-programmer types, that CRUD stands for Create Read Update Delete – the four basic operations you can perform on a data entity.

My helper makes it super-easy to produce basic CRUD web pages for any data entity, with just a couple of lines of code in your helper – a bit like Rails scaffolds but without the scaffolding! Sounds like magic, I hear you yell! Well yes, but it's my magic that I wrote from scratch so it's not magic to me ๐Ÿ™‚

It's been an easy port between ORMs mostly because the concepts and syntax map over with relatively little fuss, and actually 98% of my CRUD helper code is not concerned with the DB, but rather with running the web UI. So the few places that actually perform a DB operation needed a bit of tweaking to use the right syntax, but it's been pretty smooth sailing. Hopefully it will be easier with AR to neatly deal with many-to-many associations without having to explicitly fool around with the join table. We shall see, as that's what foxed me with DataMapper and caused me to switch.

One very important thing to mention is that when using ActiveRecord outside of Rails you have to know that it was originally written for the single-threaded Rails world. Hence it just maintains a very small connection pool (say 3) and those connections quickly run out in a threaded environment – Ramaze in my case. This leads to strange pauses of several seconds as your request handling thread waits for a connection to come free. They come free after about 5 seconds of inactivity, so you get one reasonably soon, but the multi-second pause is infuriating and very confusing. A neatly packaged solution is handily presented and well explained here: http://coderrr.wordpress.com/2009/01/16/monkey-patching-activerecord-to-automatically-release-connections/. Note that there is a link at the bottom to the single-file patch that just sorts everything out for you, so if you can't be bothered to read the explanations, head straight for that, require it in your project and you're away.

The dome of the Stephansdom cathedral in Vienna is a cracking example of baroque excellence. Here is the view straight up. Right in the very centre of the ceiling of the lantern is a dove.

AustriaCathedral
This dove in the very centre, on the ceiling of the lantern above is very similar to that at the pinnacle of Karlsdom below, but we were able to get within a few feet of the Karlsdom version courtesy of the slightly rickety scaffold reaching up all the way into the heavens.
ViennaKarsldom
I've developed a very simple webapp.RequestHandler subclass that does a couple of useful things that I need in my GAE app. They seem like pretty basic things that are worth sharing – though anyone could have done it themselves in five minutes.

class BBRequestHandler(webapp.RequestHandler):
  # Render a template with standard data mixed in.
  def render(self, template_name, template_data = {}):
    template_data.update(self.sundries())
    self.response.out.write(template.render('view/' + template_name, template_data))
  
  # Forward the request to a different handler. Assumes GET.
  def forward(self, handler_class):
    handler = handler_class()
    handler.initialize(self.request, self.response)
    handler.get()
    
  # Standard template data required for most pages.
  def sundries(self):
    return {'logout':users.create_logout_url('/')}

The intention is that sundries() should return whatever standard data your pages require that's not specific to individual pages. In my case that's data that's required for the header, footer and sidebar – like the logout URL.

You may notice that I'm not using the Python docstring format. I just can't quite bring myself to do that just yet, though I have got used to the indentation-is-block thing.

I nipped down to the local nature reserve today and it really felt like Spring had sprung. After the recent spell of miserable, cold weather, today was balmy and glorious with the smells of growing plants on the gentle breeze.

The wildlife was enjoying it too, with the resident kingfisher doing what he does best – fishing. One thing he doesn't usually do at all is come anywhere near me so I can get a really good photograph. Today though, he flew to a nearby branch and sat posed in the sun for 15 second or so. I can tell it was definitely a he as the bill is all black. This is my best shot yet of a kingfisher, by some margin.

KingfisherBig

This is quite a special lager – brewed with champagne yeast it has a very fine, light bubble and it does indeed taste like a beery champagne. Imagine a very fine champagne with the sweetness replaced with dry pils bitterness. Certainly the lingering feel in the mouth is more champagne than beer.

There are very few beers brewed in this style, so this one from Alsace is quite unique and worth tracking down. I was spurred to pick some up because Waitrose had 25% of the bottles – and it was on taste ๐Ÿ™‚ It's really very good indeed – super refreshing and drinkable (but remember it's a deceptive 5.2% ABV) but a bit unusual.

In this case I was drinking it from a Kรถlsch glass, which isn't entirely right, but seemed to suit it's delicacy. I suppose it could/should be drunk from a champagne flute!

KasteelCru
The theory is good with the new buttonless MacBook trackpads, but in practice I think it’s flawed. The whole very large surface clicks down when pushed, though it’s hinged at the far side, so it works best at the side closest to the user. So you ought to be able to use your thumb to click exactly where the button used to be, and be no worse off than before. Problem is, the button was raised up a bit above the palmrest, whereas the tracking surface is a shade below it. So now your thumb has to reach down and over the lip to click, which is a bit uncomfortable. It’s a subtle difference but I think an important one.

I’ve only had a play in the shop, so maybe I’d get used to it and maybe even change my clicking habits entirely, but it put me right off.

I've noticed that a lot of the standard Python methods on lists and dictionaries don't return anything at all – they simply modify self and return nothing.

>>> l = [1,2,3]
>>> r = l.reverse()
>>> print l
[3, 2, 1]
>>> print r
None

This is becoming extremely frustrating as it prevents chaining of method calls, which would be possible if only self was returned. This keeps catching me out if I attempt to return some_list.reverse() or dict = {'foo':bar, 'x':y}.update(some_other_dict) as I end up with None when I expected Something.

It's the little details that make a language a joy or a chore.

I ran into an interesting performance issue with my Google App Engine application, which I'm currently developing feverishly. It seems that if you use indexed array style access to an unfetched Query object, performance is atrocious. I'm fairly sure that it's doing a fetch for each access. It will also hit the 'DB' if you call count() on the Query object. Far superior is to explicitly fetch() from the Query to get a list, then use that. It's all fairly obvious really, but it took me a while to realise what was going on, perhaps because you can innocuously use the Query object as an iterator without this problem, which lulls you into a false sense of security.

So to give a contrived (and untested) example, this I would expect to be terrible performance wise:

special_days = SpecialDay.all().filter('date >=', start_date).order('date')
day = date.today()
end_date = day + timedelta(21)
sd_index = 0
while day <= end_date:
  # This count() call and the indexed access to special_days each cause a DB hit!
  if special_days.count() > sd_index and day == special_days[sd_index]:
    print 'special day'
    special_days_index += 1
  else:
    print 'ordinary day'
  day += timedelta(1)

It's easily fixed by simply adding fetch(1000) on the end of the first line, and using len(special_days) instead of special_days.count(). Also, having moved to working with a list, you can remove sd_index entirely and pop() items off the front of special_days until it's empty instead. It's a pain that there isn't a less skanky way to fetch 'all of them' without using that nasty 1000. I suppose at the very least I should create a MAX_FETCH_LIMIT constant for it in my own code, so I can centrally modify it when Google modify their max limit.

Why can't I just use an iterator anyway you may ask? Because my loop, which is similar in structure to the example above, is iterating over days between two dates and each time round the loop picking the item off the front of my list of data entities (which were fetched in date order) if it matches the day. It's all working very nicely now thanks, and I've added caching too, to save hitting the DB at all in many cases.

A funny thing appears to be happening in the mortgage market, and it's of precisely no help to me, seeing as I just want to buy a house to live in. First some facts to set the scene.

  • Bank of England base rate here in the UK is down at 1%.
  • But you can't get a new mortgage with a rate any better than 5% if you only have a 15% deposit. That's the same rate you could get just 2 years ago, when the BoE base rate was 5.25% as far as I recall.
  • 15% is a not unreasonable deposit by standards of recent years, and it's certainly a huge chunk of cash given the astronomical price of a three bed semi these days.
  • If you have a 40% deposit, you can get a new mortgage with a 2.29% rate. 
  • The price of houses is by the way still about double what it was just ten short years ago.

The net result of this is that people with vast stacks of money just sitting around in savings accounts are realising that they're not getting any interest on their stash and might be better off investing in bricks and mortar. Seeing as they have these giant piles of cash they can pay a 40% deposit no problem and take advantage of the seriously cheap mortgage deals available only to the already mega-rich. I'm told by local estate agents that young folk are now streaming into their offices with their parents in tow (they supply the briefcase full of gold bars) to get their investment property sorted as a nice little earner.

And guess what this influx does? Pushes up property prices, keeping the money-go-round spinning for those lucky enough to be on it. So, I put forward the bold statement that the decrease in base rates combined with the existing lack of credit is actually shutting non-investors out of the market. Which is really annoying because I was hoping for a cheap-houses-for-all feeding frenzy of which I could be a part ๐Ÿ™

Of course, I'm just bitter.

We stumbled across Vienna's prime schnitzel place, Figlmuller's and ordered the house speciality for lunch. It more than covered the plate and was only about 3mm thick. It tasted like those breaded turkey burgers I used to eat when I was young, which was a little disconcerting. It was basically nice, but became a bit of a chore.

FiglmullerSchnitzel