Completely custom routes
October 30th, 2008In a recent project for the New Zealand business community, we were required to have some really custom routes. An example of such routes would be geographical routes, e.g. /china, or /china/beijing.
We could try something like this:
map.country ':country', :controller => :locations, :action => :show, :country => Regexp.new(Country.all.map(&:name).join('|')) map.region ':country/:region', :controller => :locations, :action => :show, :country => Regexp.new(Country.all.each{|c| "^#{c.name}" }.join('|'))
However we get this error “Regexp anchor characters are not allowed in routing requirements”. So we can’t use requirements. However, we can use route conditions instead. With inspiration from Jamis Buck’s route monkeypatch :
# /lib/routing_extensions.rb module ThongKuah module Routing module RouteExtensions def self.included(base) base.alias_method_chain :recognition_conditions, :path_regexp end # allows recognition for paths only matching the given regexp (conditions[:path]) # allows recognition for paths not matching the given regexp (conditions[:not_path]) def recognition_conditions_with_path_regexp result = recognition_conditions_without_path_regexp result << "conditions[:path] =~ path" if conditions[:path] result << "(conditions[:not_path]=~path).nil?" if conditions[:not_path] result end end end end # /config.environment.rb require 'route_extension' ActionController::Routing::Route.send :include, ThongKuah::Routing::RouteExtensions
So now we can go :
map.country ':country', :controller => :locations, :action => :show, :conditions => {:path => Regexp.new(Country.all.map(&:name).join('|'))} map.region ':country/:region', :controller => :locations, :action => :show, :conditions => {:path => Regexp.new(Country.all.each{|c| "^#{c.name}" }.join('|')) }
Note we can have negative matches as well. I’m sure the Regular expressions gods can do a negative match use Regexp only, but hey.
We found this rails idiom to be quite useful as this allows us full customisation of routing, if we need it. We have used it successfully for Made from New Zealand, so you check it out on pages such as www.madefromnewzealand.com/new-zealand and www.madefromnewzealand.com/new-zealand/auckland.
Pastie of the code here.