Proposal: Pure Regex Router (and router wishlist)

Duane Johnson canadaduane at
Wed Aug 8 01:10:37 EDT 2007

On Aug 7, 2007, at 2:41 AM, Luke Sutton wrote:

>> So this has been an idea ever since Rails came out.  Why not use a
>> pure regular expression router in similar fashion to gsub?  I imagine
>> it working something like this:
>> Merb::Router.prepare do |r|
>>    r.add %r[^/(.*)/(.*)/(\d+)$], :controller => '\1', :action =>
>> '\2', :id => '\3'
>>    r.add %r[^/user-(\d+)$], :user_id => '\1', :controller =>
>> 'free_area/users', :action => 'index'
>> end
> Certainly very powerful, but I'm a little bit dubious of it's  
> usefulness — is your intent to use regular expressions like this to  
> reduce redundancy in route declaration?
> In that case I think the routing DSL could be extended to make that  
> possible. That would be friendlier to noobs like yours truly.

I realize I'm fighting against long-held tradition.  Luckily, I'm so  
much against the current way of things as I am deterred by its  
inflexibility at times (or at least, the inflexibility of Rails  
Routes).  I feel like we should have a Pure Regex Router as the  
foundation, and then other router-adding styles built on top of that.

Some of the things I've tried to do that I couldn't:

- Use symbols other than "/" to denote a partition between segments.   
For example:

- Use specific characters to reduce the size of URLs, i.e. map url  
parts to other things.  For example, suppose I wanted to map the CRUD 
+ actions like this:
	i => index
	n => new
	c => create
	r => show
	e => edit
	u => update
	d => delete

	Such that the following URLs are valid:
	/users-i (maps to 'users' controller, 'index' action)
	/movies-u (maps to 'movies' controller, 'update' action)

	r.add %r[^/([^-]+)-([increud])$], :controller => '\1' do |match|
		map = {'i' => 'index', 'n' => 'new', 'c' => 'create'}  # etc.
		{:controller => match[1], :action => map[match[2]]}

- Map segments to other segments.  For example, suppose you have  
several controllers within an admin "module", and let's say you  
decide later that these controllers should be externally accessible  
from the "superadmin" folder as well.  Currently, you would need to  
create a route for each controller:

	r.add '/superadmin/users/:action/:id', :controller => 'admin/users'
	r.add '/superadmin/movies/:action/:id', :controller => 'admin/movies'
	r.add '/superadmin/categories/:action/:id', :controller => 'admin/ 

	Instead, we should be able to do something like this:

	r.add '/superadmin/:controller_segment/:action/:id', :controller =>  

- Type-agnostic routing.  For example, suppose I have a database of  
many types of objects that all share a universally unique identifier  
such as a GUID.  By looking at the URL only, I can't tell what the  
object is--so, first I need to do a database lookup to determine what  
type of object the referenced thing is and then route it to a  
controller/action pair.  For example:


	r.add '^/(\d+)$' do |match|
		if obj = MyObject.find(match[1])
			{:controller => obj.controller, :action => 'index'}

	In the above example, the router can only determine where to route  
to after a database lookup.

>> In addition, I propose we add more options to the router so that the
>> protocol, port, and domain become available:
>>    r.add :path => %r[^/([^\/,?]*)$], :domain => /^(blog|news)
>> \./, :controller => '\1', :action => 'index'
> Now this is a top idea! I can imagine many situations where this  
> would be handy. For example you might wish to route secure  
> connections differently.
> In addition to protocol, port and domain, it would be very useful  
> to have access to sub-domains in the route declarations.

Yes, it would be good.  Once we finish this discussion and everyone  
is happy with the ideas, I'll see if I can add incorporate them into  


More information about the Merb-devel mailing list