===========================
  Differences with Routes
===========================
:Author: Martin Blais <blais@furius.ca>
:Date: 2006-04-21
:Abstract:

    A short email sent to the Routes/Pylons list to announce Ranvier and
    stimulate discussion about its differences with Routes.  If you're wondering
    how Ranvier differs from existing systems, this is perhaps a good summary.


I've had a few ideas over the weekend about a routing system for URL
mapping for my application, that shares a lot of similarities with
the Routes system.  I implemented it, wrote some tests, and
converted my web application code to use it and I'm thorougly happy
with it and will release it soon.  I thought some of the Pyloners
might be interested in having a look, because it is very similar to
Routes and there may be some synergy opportunities/ideas that we may
feed each other's projects on.  Here are the key differences (I
won't list the similarities, there are many):

* There is no forced concept of controller/action/view, etc.  A path
  is just a list of components and variables embedded in it.  Any
  pattern of components/fixed names in the URL is legal.  I'm not
  sure Routes also does that, I suspect it does, but the
  documentation is ambiguous about this, it seems to assume some
  stuff from Ruby, like that of having a controller/action/id
  pattern, which IMO is not necessary, but the tests indicate
  otherwise (in any case, this should be clarified in your docs IMO,
  you should explain what controllers and actions mean in your
  context, I'm not super familiar with RoR so this is a bit
  confusing, I'm guessing, but maybe I'm guessing wrong)

* There is no "connect" method like in Routes.  Rather, the pattern
  matching algorithm for matching a URL forward to a request string
  is by using a resource tree with a chain-of-responsibility
  pattern, where each resource may "eat up" zero, one or more
  components and delegate to the next in the chain -- from the root
  of the tree toward leaves.  I think Twisted has something like
  that.  The resource (controller) classes declare the possible
  branches that they can propagate and this is how the mapper builds
  itself, by visiting the tree and asking each node for its
  possibilities.  You establish the tree of resources on your site
  by creating this resource tree, once for your app.  IMO an
  advantage of this is that you can easily combine resources to put
  common code in the path of a subtree of URLs, which can e.g. fetch
  stuff from a database and propagate it on a context object that is
  passed along the chain of resources (what you call controllers).
  I find that this is also a nice way to setup security privileges
  for entire subtrees (resources don't have to eat up path
  components at all, I can have a resource just check for some
  credentials and delegate if ok, return a not-found error if not).

* All linkable resources (e.g. leafs, indexes) are unconditionally
  assigned a unique resource-id.  By default this uses the name of
  the resource handler class, which for the most part there is a
  single instance of.  The resource ids are used to generate URLs
  from the web application code.  This way the web app code NEVER
  has to see ANY urls, there is total and complete decoupling
  between the "world of URLs" and the "world of source
  code/handlers" (I see them as callbacks, really).  You could
  completely rearrange the layout of the resource tree/URLs and all
  the pages will still keep working (as long as you always use the
  mapper to generate the URLs).  Moreover, this means -- like in
  Routes -- the all URLs generated via the mapper are valid.

* My mapper can list the render the entire set of resources that the
  web app may serve.  I think this is extremely cool, to be able to
  see all the pages that your server offers (Routes does that too,
  no?  I haven't seen it on the site).  Also, there is a fancier
  resource that uses the resource handlers docstrings to provide a
  human-readable version of the list of resources on the server, and
  what their role is.

  One of the coolest applications of this is that my automated
  mechanize test program fetches this list before running, and the
  mapper can accept it and reload itself from that text (apart from
  the resource objects themselves, of course, the test program does
  not share code with the web app at all).  Then the test program
  uses that reconstructed mapper to fetch the required resources
  using only resource-ids.  This means that if the URLs change the
  test programs keep working, no worries.  Also, I can more easily
  reuse the test program for e.g. user management resources over
  different web applications, even if their URL layout is completely
  different.

* I did not implement getting the defaults from the request object
  like Ruby/Routes (i.e. specifying only some of the parameters),
  simply because I find it a bit too implicit for my taste (this is
  rather personal).  The mapper, however, can accept to be passed an
  object or dict to fetch missing values.  Since the default
  behaviour of the resources that "eat up" URL components is to add
  them as attributes to a context object that is passed along, I can
  just pass in that context object to provide similar behaviour.

* Static validation in code: I provide a script that given a URL of
  the resource mapper rendering, will reload a mapper, grep all your
  source code for resource ids (given that you use a unique pattern,
  by default they are strings like this: @@ResourceName) and will
  warn you if your code is attempting to generate links to resources
  which do not exist.  I have found this extremely quick and useful
  to prevent errors.

* Coverage Analysis (yet to be implemented, should be done within a
  few days):  Since all fetching of resources and rendering of links
  goes via the URL mapper, I can easily record access and renders to
  a file/DB and provide results on a resource or from the
  command-line.  (This will be quasi trivial to implement within the
  current system.)  This means that I can run my automated tests and
  find out which resources have been tested or not.  This also
  allows me to find old cruft, unused resources still on the server
  (hey, an app evolves).

* Like Atocha and other of my web app components, the code is
  completely and entirely ORTHOGONAL to any web app framework out
  there (I consider this *the prime directive*).  You can even use
  it with CGI scripts if you like (the demo app does that).

Anyway, if anyone is interested, here is the link:
http://furius.ca/ranvier/

There is a simple running demo here:
http://furius.ca/ranvier/demo/

In particular:
http://furius.ca/ranvier/demo/resources
http://furius.ca/ranvier/demo/prettyres

Ranvier's documentation:
http://furius.ca/ranvier/doc/ranvier-doc.html


For now this is just a one-man project but if some people would like
to contribute new stuff to it I'm very open to patches.  I'll
release this as soon as I find time to complete the documentation
nicely.  If you see opportunities for merging some of the stuff let
me know.  In particular, I think it would be possible to build an
interface for Ranvier that is similar to the connect() interface of
Routes, creating a tree of resources dynamically, but I'm not sure
of some of the issues if I did that (and I don't need it now, so I
won't indulge).

Anyway, I would be interested in comments or criticisms about it,
whether you think it has disadvantages, advantages, etc.  Any
comments and discussion welcome.

