## Routing Filter

This plugin is a wild hack that wraps around the complex beast that the Rails
routing system is to allow for unseen flexibility and power in Rails URL
recognition and generation.

As powerful and awesome the Rails' routes are, when you need to design your
URLs in a manner that only slightly leaves the paved cowpaths of Rails
conventions, you're usually unable to use all the goodness of helpers and
convenience that Rails ships with.

## Usage

This plugin comes with a locale routing filter that demonstrates the
implementation of a custom filter. 

The following would be a sceleton of an empty filter:

    module RoutingFilter
      class Awesomeness < Base
        def around_recognize(route, path, env)
          # Alter the path here before it gets recognized. 
          # Make sure to yield (calls the next around filter if present and 
          # eventually `recognize_path` on the routeset):
          returning yield do |params|
            # You can additionally modify the params here before they get passed
            # to the controller.
          end
        end
    
        def around_generate(controller, *args, &block)
          # Alter arguments here before they are passed to `url_for`. 
          # Make sure to yield (calls the next around filter if present and 
          # eventually `url_for` on the controller):
          returning yield do |result|
            # You can change the generated url_or_path here. Make sure to use
            # one of the "in-place" modifying String methods though (like sub! 
            # and friends).
          end
        end
      end
    end

You then have to specify the filter explicitely in your routes.rb:

    ActionController::Routing::Routes.draw do |map|
      map.filter 'awesomeness'
    end

(I am not sure if it makes sense to provide more technical information than
this because the usage of this plugin definitely requires some advanced
knowledge about Rails internals and especially its routing system. So, I
figure, anyone who could use this should also be able to read the code and
figure out what it's doing much better then from any lengthy documentation.

If I'm mistaken on this please drop me an email with your suggestions.)


## Rationale: Two example usecases

An early usecase from which this originated was the need to define a locale
at the beginning of an URL in a way so that 

* the locale can be omitted when it is the default locale
* all the url\_helpers that are generated by named routes continue to work in 
a concise manner (i.e. without specifying all parameters again and again)
* ideally also plays nicely with default route helpers in tests/specs

You can read about this struggle and two possible, yet unsatisfying solutions
[here](http://www.artweb-design.de/2007/5/13/concise-localized-rails-url-helpers-solved-twice).
The conclusion so far is that Rails itself does not provide the tools to solve
this problem in a clean and dry way.

Another usecase that eventually spawned the manifestation of this plugin was 
the need to map an arbitrary count of path segments to a certain model 
instance. In an application that I've been working on recently I needed to 
map URL paths to a nested tree of models like so:

    root
    + docs
      + api
      + wiki
  
E.g. the docs section should map to the path `/docs`, the api section to 
the path `/docs/api` and so on. Furthermore, after these paths there need to be 
more things to be specified. E.g. the wiki needs to define a whole Rails 
resource with URLs like `/docs/wiki/pages/1/edit`.

The only way to solve this problem with Rails' routing toolkit is to map
a big, bold `/*everything` catch-all ("globbing") route and process the whole 
path in a custom dispatcher.

This, of course, is a really unsatisfying solution because one has to
reimplement everything that Rails routes are here to help with: regarding both 
URL recognition (like parameter mappings, resources, ...) and generation 
(url\_helpers).

## Solution

This plugin offers a solution that takes exactly the opposite route. 

Instead of trying to change things *between* the URL recognition and
generation stages to achieve the desired result it *wraps around* the whole
routing system and allows to pre- and post-filter both what goes into it 
(URL recognition) and what comes out of it (URL generation).

This way we can leave *everything* else completely untouched. 

* We can tinker with the URLs that we receive from the server and feed URLs to 
Rails that perfectly match the best breed of Rails' conventions. 
* Inside of the application we can use all the nice helper goodness and 
conveniences that rely on these conventions being followed. 
* Finally we can accept URLs that have been generated by the url\_helpers and,
again, mutate them in the way that matches our requirements.

So, even though the plugin itself is a blatant monkey-patch to one of the
most complex area of Rails internals, this solution seems to be effectively
less intrusive and pricey than others are.

## Etc

Authors: [Sven Fuchs](http://www.artweb-design.de) <svenfuchs at artweb-design dot de>  
License: MIT 