Rerouting Rails

One of the things I talked about recently was the routing in Ruby on Rails. Simply put, it’s horrible. I mean, it’s clever, but it’s a long way from being either clear or elegant. Rather like the Dark Side, metaprogramming is seductive—but it’s rarely the right solution to an algorithmic problem. There’s a lot of code generation in the routing code, and it’s very hard to follow. Not impossible, but hard.

You might ask why it matters, given that it works as it is now. For me, the most important reason is that it’s inelegant. Although my initial revulsion is aesthetic, inelegance hides a lot of problems, because code that’s hard to read is code that’s hard to analyse, improve, and debug.

Significantly, the recent security vulnerability in Rails was related to routing, which is a good reason to look at it with a critical eye.

Jamis Buck has written a few articles explaining routing, covering the DSL itself, route recognition, and route generation. They give an insight into how and why it works.

But I still think it could be implemented better, so I stayed up late last night and started to implement a tree-based routing system. I’m not sure if this is the best kind of tree to use, but I think it’s the step in the right direction.

So far, I’ve done the tree building and forward matching of routes. Recognising a route is very easy once you’ve built the tree: you just walk the tree starting at the root node for each segment of the path, choosing the leftmost matching node each time. Including parsing the routes definition itself, it’s only a couple of hundred lines.

With a little extra code, it’s also easy to throw the tree into Graphviz, which makes it a lot easier to visualise. Here’s an example tree diagram, using the routes file from Radiant CMS.

routing tree diagram

Next, I’ll implement route generation—I have a few ideas about that—and compare the performance with the current Rails routing code. Then, maybe, I’ll start to look at optimisation.

Comments

  1. Jeremy Kemper

    Wrote at 2006-11-18 00:04 UTC using Firefox 2.0 on Linux:

    Nice work, Paul! I’d love to see cleaner + faster routes, particularly for url generation. Have you tried your recognizer with the Action Pack unit tests?
  2. Paul Battley

    Wrote at 2006-11-18 00:38 UTC using Firefox 2.0 on Mac OS X:

    I haven’t tried the Action Pack tests yet, although those are definitely on my list. The tests I have at the moment check a subset of functionality, but it’s a subset that’s comprehensive enough to cover most routing files, I think. Regular expression segment rules are a current notable omission, and I’m sure that there are a few other features that I’ll need to add to get parity with the current Rails implementation.

    I’m pretty confident that I can come up with cleaner URL generation; whether it’s faster or not, we’ll have to see!