spacer
spacer spacer spacer spacer spacer spacer
10 Feb 07

Hot Routes

Tags: coding el eldiablo programming ruby tech

Last day or so I've come up against a couple of intriguing Rails problems while trying to knock up some plugins for an app I'm writing. I'll write up the second of the two problems later, but here goes the first...

Put simply, I wanted to define a route within my plugin. My plugin implemented a controller (and also contained a view for that controller, see one of the latest features to hit edge Rails ahead of Rails 2.0).

I searched to try and see if anyone had come up against a similar task, but didn't see any concrete answers. My testing led me to realise that every time a call to ActionController::Routing::Routes.draw is made, it completely clears and re-generates routes based on the block passed to that method. So simply calling draw with a new block containing my required route wouldn't work; it'd overwrite other routes, or end up getting overwritten by other routes later in the chain.

I then figured it was time to get cracking with some meta-programming, and that I was going to have to re-define and extend the draw method in order to be able to map the routes I want, and do it in a way that'd be flexible and fair to the original Rails routes file, and other plugins that wanted to toy around with routing. I came up with the following:


module ActionController
    module Routing
        class RouteSet
            alias draw_old draw
            def draw
                draw_old do |map|
                    map.connect "controller/action", :controller => "mycontroller", :action => "myaction"
                    yield map
                end
            end
        end
    end
end


Let's give this a quick run-through... I'm re-opening the ActionController::Routing module, and specifically the RouteSet class where the draw method exists. I'm using alias to copy the existing draw method to a method name "draw_old", before re-defining the draw method itself. Within my version of the draw method, I'm calling the old one and passing it a block that firstly defines the routes I wanted to add to the application, and that then yields the appropriate mapper object back to any block passed in to the draw method itself. Dependent on where you want your route to appear in the scheme of things, you could always map your plugins custom routes after you yield the mapper to the calling block, so that they appear after any other routes. Another tweak would be to alias the existing draw method to something like "draw_old_APPNAME", where APPNAME is the name of your application. This would ensure that if multiple plugins implemented something similar, that they then wouldn't clash.

There may be a better way to tackle the problem, but after half an hour of working the problem over (mad props to my boy Mike for helping me tweak the solution into something useful and re-usable), I think I came up with a pretty solid answer, and with a bit more time, something that could probably be wrapped up into a module or plugin all of its very own. Bottom line? Ruby as a language rocks, the dynamic nature and meta-programming features opens whole new doors of functional programming to me, and I'm having to really think outside of the box to see some of the amazing things you can do with it.
Comments

Leave a response

Comment

Back to recent posts
My name is Elliott Draper, and I'm a developer in the UK, specialising in Ruby and Ruby on Rails.

You can find out more about what I do here, more about me here, or examples of my work here.
spacer
Most recent posts
  • "RailsConf 2009" on May 28 2009
  • "Freebird" on April 11 2009
  • "Foot Locker Unlocked" on February 24 2009
Syndication
Articles: (RSS)
Comments: (RSS)

Tags
rufio el eldiablo personal coding mono programming scrawl tech xframework blogging web 20 computers pc ruby dotnet gaming xbox360 geekiverse keynote macworld blog rsync ssh apple appletv iphone ipod itunes macbook macbookair amazon beanstalk capistrano ec2 git heroku links merb rails rb rubyonrails s3 360 fifa fifa2008 football pes pes2008 soccer xbox sdk github scm sourcecontrol britain budget democracy economics finances labour liberals politics tories automobile car miscellaneous tyre feather mike merb manage gem rubyforge activereload lighthouse defer_to router routing contributions coverage irc plugins job net work brightkite dropbox evernote friendfeed invites socialthing twitter google groups mailing list appstore mac o2 datamapper albums lesser known classics mcmlxxxv music slices caesars palace las vegas wedding adium fluid growl javascript meebo userscripts blocks eval proc snippet qotsa songs for the deaf advent advent 4211 laptop msi msi wind netbook notebook rumble edraper downtime god restart ejdraper reboot code coverage cover up slice
Archives
  • May 2009 (1)
  • April 2009 (1)
  • February 2009 (1)
  • January 2009 (4)
  • October 2008 (3)
  • July 2008 (4)
  • June 2008 (6)
  • May 2008 (4)
  • April 2008 (6)
  • March 2008 (5)
  • February 2008 (2)
  • January 2008 (2)
  • December 2007 (1)
  • October 2007 (2)
  • March 2007 (1)
  • February 2007 (4)
  • January 2007 (2)
  • September 2006 (4)
  • August 2006 (7)
  • July 2006 (4)
  • View all
 
All text, design and content is copyright © 2009, Elliott Draper trading as ejdraper.com.
 
spacer
spacer
 
gipoco.com is neither affiliated with the authors of this page nor responsible for its contents. This is a safe-cache copy of the original web site.