Lars Pind

internet software, coaching, and entrepreneurship

Lars Pind - internet software, coaching, and entrepreneurship
Check out Coach TV, my video blog on happiness and personal development for geeks.

RELEASE: Redirect Routing Plugin for Rails

July 19, 2006 · See comments

Here’s another simple plugin hot on the heels of my previous ExceptionTextable plugin: A plugin to add redirects straight in your routes.rb file.

First, to install say:

script/plugin source http://svn.pinds.com/rails/plugins
script/plugin install redirect_routing

Then add this to your routes.rb:

map.redirect '', :controller => 'events'

And now the root of your site will redirect to the index action of the events controller.

Why not just map.connect? Because map.connect causes the URL in the browser to stay at /, which isn’t very RESTful.

Note that you can also pass a string:

map.redirect 'lars', 'http://pinds.com'

Now /lars will redirect to my blog.

See the README for more details. Enjoy!

blog comments powered by Disqus
  • 1 Pelle // Jul 19, 2006 at 01:03 AM

    Very useful. I will definitely use it.
  • 2 Jarkko Laine // Jul 19, 2006 at 09:07 PM

    Very cool, Lars. That sounds extremely useful for supporting legacy url's. Any plans to make it support variables/regexps? Like:
    map.redirect 'blog/:id', 
       Proc.new{|id| 
            @post = Post.find(id)
            {:day => @post.day, ... , :title => @post.title}
      }
    
    Ok, maybe that was a bit too involved... but it *would* make supporting textpattern-type url's easy in Typo :-)
  • 3 Lars Pind // Jul 19, 2006 at 11:07 PM

    Interesting idea. I'm thinking the routes should stay declarative. They're not meant as a replacement for controllers. I could see how you'd want to do some simple regsubbing or use of parameters, but I think it ends there.
  • 4 Thijs van der Vossen // Jul 20, 2006 at 09:06 AM

    Very nice! Would be great to have this in Rails by default. Why not try to get it in there for the next release?
  • 5 Lars Pind // Jul 20, 2006 at 09:17 AM

    The only problem is that I'm creating a special controller behind the scenes and then leveraging the normal controller and response's url rewriting and redirecting capabilities. The rewriting part is actually handled by the Routing system, so that should be easy, and sending the redirect is trivial, so that could be done as well, but it wouldn't be completely DRY. If there's interest from core I'll be happy to explore.
  • 6 robin // Jul 30, 2006 at 08:13 PM

    when i put this in my vendors/plugins I get the following... ... /dependencies.rb:123:in `const_missing': uninitialized constant Mapper (NameError) from /usr/local/lib/ruby/gems/1.8/gems/activesupport-1.3.1/lib/active_support/dependencies.rb:133:in `const_missing' rails don't start.. something I'm missing?
  • 7 Lars Pind // Jul 30, 2006 at 08:27 PM

    Did I mention this only works with edge and the rewritten routing implementation?
  • 8 Daniel Butler // Sep 19, 2006 at 06:01 PM

    I get the same error as robin while I'm trying to set this up on a customized Typo installation, which is pegged to non-edge Rails. Anyone have any suggestions about how to accomplish redirects (or support for legacy URLs) without this plugin?
  • 9 Craig Barber // Mar 20, 2007 at 05:06 PM

    I altered your plugin to support: map.redirect '/old_controller/:action', :controller => 'new_controller' by adding the following to RedirectRoutingController: def method_missing(action) redirect_to params[:url_options].merge({ :action => action }) end P.S. - I *really* like the automatic code detection. Is that part of typo?
  • 10 Lee Iverson // May 10, 2007 at 10:44 AM

    OK, so I bit the (very soft) bullet and got this working with regexps in the redirect options. The changes are simple:
    module RedirectRouting
      module Routes
        def redirect(path, options={})
          url_options = { }
          connect_options = {
            :controller => "redirect_routing", :action => "redirect",
            :url_options => url_options }
          options.each do |key,value|
            if [:controller, :action].include?(key)
              url_options[key] = value
            else
              connect_options[key] = value
            end
          end
          connect path, connect_options
        end
      end
    end
    
    and
    class RedirectRoutingController < ActionController::Base
      def redirect
        url_options = params.delete(:url_options)
        redirect_to params.merge(url_options)
      end
    end
    
  • 11 Michael Hartl // Aug 06, 2007 at 06:44 PM

    Hi Lars, Thanks a bunch for this plug-in. I just used it on the blog for a Rails book I wrote with Aurelius Prochazka, one of Philip Greenspun's cofounders at ArsDigita. File under: small world. :-) Cheers, Michael
  • 12 Lars Pind // Aug 08, 2007 at 10:15 AM

    Hi Michael Yeah, that is funny. Small world. Aure did tell me that he was writing a book a while back. Congrats on getting it done! //Lars
  • 13 Ian Heggie // Oct 17, 2007 at 10:58 AM

    Hi, A variation on the theme to handle :action as well as keep other options: {{{ class RedirectRoutingController < ActionController::Base def redirect(action = nil) args, options = params[:args] || [], {} options = params[:args].pop if Hash === params[:args].last response.headers["Status"] = "301 Moved Permanently" if options.delete(:permanent) raise ArgumentError, "too many arguments" if args.size > 1 options.merge({ :action => action }) if action redirect_to args.empty? ? options : args.first end def method_missing(action) redirect(action) end end }}}
  • 14 Neil Smith // Dec 13, 2007 at 04:14 PM

    Hi there. This is a nice plugin that I'm using for supporting some legacy urls. However, although everything worked fine in the 'development' environment, things were a bit odd in the 'production' environment (I'm running Rails 1.2.5 on Mongrel.) I found that the first time I tried to redirect, everything worked fine - but on subsequent hits to the page that should redirect, I'd see "ActionController::RoutingError (no route found to match "/redirect_routing/redirect" with {:method=>:get})" - and the args being logged were blank, which was not the case on the first request. After a little bit of digging, it appears to be related to the modification of params[:args]. For instance, this quick fix - of 'dup'ing before we begin - appears to make things work for me in Production: class RedirectRoutingController < ActionController::Base def redirect arguments_from_params = params[:args].dup args, options = arguments_from_params || [], {} options = arguments_from_params.pop if Hash === arguments_from_params.last response.headers["Status"] = "301 Moved Permanently" if options.delete(:permanent) raise ArgumentError, "too many arguments" if args.size > 1 redirect_to args.empty? ? options : args.first end end But things still aren't quite right: I'm using permanent redirects, and I get {:permanent => true} being passed through on the first request, but not on subsequent requests - this then generates me a 302 Moved Temporarily redirect from the 2nd time onwards. (Again, this is only the case in the Production environment.) Any thoughts on what might be causing this? Many thanks again for the plugin! Cheers, Neil.
  • 15 Neil Smith // Dec 13, 2007 at 04:18 PM

    (Rats. Sorry about the formatting.)