Custom tags for node links in Drupal 6

In this post I’m going to try and explain how to add custom tags that link to node pages to a Drupal 6 input format. That probably sounds a bit far-fetched, so I’ll attempt to clarify by using my own project as an example.

last.fm has this nifty feature where you can write [artist]Meshuggah[/artist] and it’ll turn into a link to that artist’s last.fm page. A set of custom BBCode tags, basically. The project I’m working on, got-djent.com, is also a website about music, and will contain a band/album database maintained by the users in a wiki-like fashion. On the front page, it will be possible to post news articles. I thought it would be nice if band and album pages could be linked from these articles easily, by using custom tags.

Installing the customfilter module

What I set out to implement was having <band>Meshuggah</band> turn into <a href="http://got-djent.com/node/2">Meshuggah</a>, e.g. a link to that band’s page. Something like this is best implemented as a “custom filter” in Drupal 6. To be able to do this, you have to install and enable the customfilter module first. You can get it here. Once you have uploaded it to the modules/ directory of your Drupal install, you can enable it under Administer > Site Building > Modules (admin/build/modules).

Read More »

Fixing lousy introspection support in Python DB APIs (partially)

For my internship at Think Wize, I’ve been working on a custom Django management command that compares the current model definitions (models.py) and the current database schema, and tries to spot the differences. I’ve called it checkdb. Optionally it can also attempt to fix them, with checkdb --fix.

syncdb is not agile

Django’s syncdb management command, used to synchronise the database with the model definitions, is often criticised because it refuses to alter already existing tables. Django’s development team stands by this. They reason that altering the tables to match changed models is a very complex and ambiguous process, which is too risky to be completely automated. They are probably right. There are so many parameters to take into account. In addition, it is basically impossible to tell whether a field has been changed, or whether a field has been removed and another one added.

This means that, when you change your models during development (and you most likely will, frequently), syncdb is of no use to update your database schema accordingly. Django’s documentation suggests that you use the sql command, which prints out the SQL that you could use to create the entire database schema matching the current model definitions from scratch. It is then up to you to distill some ALTER TABLE statements out of this.

Read More »

Apache rewrite rules are almost as horrid as XSLT

It’s time for a rant. I haven’t posted in a while because I haven’t been doing much that might be of interest to anyone, in terms of coding. Apart from my internship, perhaps; I’m working at Think Wize, a company based around Django, for six weeks. They are hoping to set up a continuous integration environment of sorts, and I’ve been given a few tasks to help make this happen. The first few weeks I’ve mainly been trying to get their codebase to play nice with South, a schema migration tool for Django. It’s been quite a challenge. I’m not sure if I’m at liberty to say much more about the subject, but that’s not what this post was going to be about anyway.

Nope, this is a rant. I just spent almost two hours trying to figure out how to get Apache to remove the “www.” from URLs. mod_rewrite, goddamn. It isn’t so much the horrible syntax, or the contradictory information to be found about it, as the fact that it was basically ignoring what I wrote the whole time. Really, really frustrating. I don’t know why, either. Feel free to continue reading and let me know what I was doing wrong, if you want.

Read More »

Capturing the mouse with jQuery

I’ve been working on a Javascript-driven Django application pretty much non-stop for the last week or so. I’ll leave my experiences with the Django framework for another post1. There’s more than twice as much Javascript code in this application than there is Python code, so I can’t really claim that I know Django yet, to be honest.

Anyway, the application I am working on is similar to Google Calendar in terms of user interface. Basically, it allows VTK’s2 praesidium and volunteers to indicate when and how they wish to help for every activity they organise. For each activity, a list of shifts is presented in a timetable. Usability is the main concern here, so everything is mouse-driven and easy to use. At least, that’s what it is intended to be. There’s a screenshot here, which should help to get the general idea. The most interesting part is the administration interface (for the creation of the shift lists), which allows for shifts to be drawn, resized and moved around on the grid with the mouse. jQuery and its many plugins (jQuery UI in particular) have made it relatively easy to get this done.

However, there was one thing that bothered me: DOM elements only receive mouse events when the mouse pointer is within their bounds. This is expected behaviour, but sometimes it’s nice to be able to have a certain element capture the mouse (i.e. keep receiving mouse events as long as a button is pressed, regardless of the position of the pointer), for example when dragging to scroll. Normally, when you accidentally move the mouse pointer outside of the scrollable area, the scrolling will stop because the DOM element is no longer receiving the mousemove event. In addition, this means that the element will never receive the mouseup event. I often perform cleanup actions in a mouseup handler; in this example, the mouse cursor might be changed during dragging, so it has to be reset afterwards. If the event is never triggered, this leaves the application in a “dirty” state.

Read More »

Notes

  1. ↑1 Maybe even throw in a few comparisons with Rails… can you smell the trolls already?
  2. ↑2 VTK is the fraternity for engineering students at Ghent University.

Scoped mixins

A while ago I read one of Peter Harkins’s posts about open classes in Ruby, and how insanely awesome and useful they are. As you can probably tell, I wholeheartedly agree. Open classes are just one of those things that make me choose Ruby over pretty much anything else, whenever I get the chance to do so (though if I’d have to name the one killer feature, I’d probably say ‘blocks’).

I vastly prefer this:

class Array
  def rand
    self[Kernel::rand(self.size)]
  end
end
 
a = [1, 1, 2, 42, 24024]
a.rand # => 24024
a.rand # => 42

to this:

Read More »

Installing Phusion Passenger on Ubuntu 8.04

There seems to be a bug in passenger-2.0.6 that makes the Apache module installation fail. I was just installing Ruby Enterprise Edition 1.8.6-20081215 and Phusion Passenger (AKA mod_rack or mod_rails), and it bailed out on me saying:

root@evidence:~# /opt/ruby-enterprise-1.8.6-20081215/bin/passenger-install-apache2-module
[...]
Compiling and installing Apache 2 module...
cd /opt/ruby-enterprise-1.8.6-20081215/lib/ruby/gems/1.8/gems/passenger-2.0.6
/opt/ruby-enterprise-1.8.6-20081215/bin/ruby -S rake clean apache2
/opt/ruby-enterprise-1.8.6-20081215/bin/ruby: No such file or directory -- rake (LoadError)

--------------------------------------------
It looks like something went wrong
[...]

Read More »

Moving out!

Until today, all my stuff was on a shared host. Didn’t matter much for this blog, but trying to run Rails applications on prehistoric technology like FastCGI got tiresome quickly. In addition, the server I was hosted on was frequently having issues since a few weeks (at one point, I witnessed it showcasing a load average of 240 8O something was filling up all memory and swap space, I think). So I decided it was time for me to get myself a proper hosting account: this blog is now hosted on a VPS :)

Migrating WordPress blogs sure could be easier. I used this guide, but I had to change some URLs in the database manually before everything would work properly. Ah well, it could have been worse! I will also try to finish the stylesheet and add some cosmetic improvements in the near future. I don’t know if anybody has noticed, but the archive pages are mess right now. I also need to tweak things a bit further to balance reasonable performance with memory usage. Apache is such a hog. As a consequence, the server will probably be down occasionally in the next few days. My apologies on beforehand if this bothers anybody.

So yeah. Update your bookmarks (ha ha). http://code.lemuria-nation.net/ is now http://benanne.net/code/! I have installed a redirect at the old location, but I don’t plan on renewing that domain, so it’ll be gone in a month or so.

Seeing as this is just a short note to let everybody know about the move, I can throw in some completely unrelated stuff: read Abstruse Goose. It’s awesome! Also check out Brendan Gregg’s collection of special sysadmin tools!

There, that’s it. Don’t worry, my next post will be chock-full of code again :)

define_method and argument semantics

define_method is an odd creature. Paul Gross’s post about its unusual behaviour inspired me to do some research. I even went and browsed through Ruby’s source to attempt to understand it, but that turned out to be unnecessary: I reimplemented it in pure1 Ruby. In this post, I’m going to try and explain why define_method behaves the way it does.

Methods vs. blocks

Methods and blocks in Ruby are similar things; they are both containers for code, and both of them can accept a number of arguments. On the other hand, the scoping rules and argument semantics for blocks and methods are very, very different.

Read More »

Notes

  1. ↑1 Well, pure… it isn’t pretty, but it is Ruby :D

Javascript arrays smell

Last night I was writing some Javascript for a Django1 application I’ve been working on. I was discussing some of Javascript’s quirks on IRC with someone else who was also scripting.

He wanted to know what happens when you add both values indexed by number, and values indexed by strings (e.g. expando properties – no, I’m not making this up); particularly how the Array.length property would deal with that. I told him that in Javascript, length always returns the largest integer key value plus one. I’m not sure if that’s 100% correct, but that’s how I remember it, and his tests seemed to confirm this.

// Relevant output is in the comments.
var foo = ["bar"];
foo.length; // => 1
foo[1000] = "baz";
foo.length; // => 1001

Read More »

Notes

  1. ↑1 Yes, you read it right, Django! At VTK, the fraternity for civil engineering students, everyone uses the Django framework for web development. Seeing as I volunteered to write an internal shift management application, I’m delving into it as well. It’ll be interesting to see for myself how it compares to Rails :)

Merb is getting merged into Rails 3! Hell yes!

Ruby on Rails

Ruby on Rails

Rails is an MVC web development framework for Ruby. Rails is awesome and magical! Rails helps speed up development, and it’s just a lot of fun to use because it takes care of all the stuff that is annoying about developing web applications. Most of it, anyways.

Merb is an MVC web development framework for Ruby. Merb is probably awesome too, though I wouldn’t know because I’ve never really used it. “Merb” is a contraction of Mongrel and ERb, because originally all it did was serve ERb template pages through Mongrel. However, it’s turned into a lot more than that, and has become somewhat of an alternative to Rails.

Merb is Mongrel + ERb

Merb is Mongrel + ERb

The main difference with Rails is its underlying philosophy: Merb is framework-agnostic, focusses on performance and has a fixed public API. Until recently, Merb had the advantage over Rails of being thread safe. Check out this interview with Yehuda Katz if you want to know more about Merb and how it differs from Rails.

Apparently, Merb and Rails are joining forces. It almost sounds like a bad April fools joke, except it’s Christmas. Merb and Rails are different. In addition, it seemed like their development teams and communities sorta hated each others guts until very recently.

Read More »