An interesting problem came up today at work: we needed a send-to-a-friend feature for a website that needed to send the URL you were currently on to a friend.

No problem, I thought: use the referrer - or better, pass through the current URL to the send-to-a-friend controller.

But things were not that easy, because certain controllers needed things out of your session to work - notably a search controller, where going to "/search" wasn't much use without the search string that lived in your session.

I pondered for a while, and concluded life would be easy if I could get the URL into a hash containing something like {:controller => "search", :action => "index", :foo => "bar"} - then I could simply inject a few extra variables into the hash if :controller == "search" and turn the whole thing back into a URL with url_for.

The resultant code looks really simple, but this took me quite some Googling and digging into the Rails docs to get this working, so I present this code in case it saved any other poor soul some time:

First, we make a URI object from the referrer (or variable you're passing in, if you prefer):

RUBY:
  1. url = URI.parse(request.referrer)

Then we ask the Rails routing system to create a {:controller => "foo", :action => "bar"}  hash from that URL's path:

RUBY:
  1. route = ActionController::Routing::Routes.recognize_path(url.path)

Next up, merge any parameters from that URL in, using Rails' implementation:

RUBY:
  1. route.merge! ActionController::AbstractRequest.parse_query_parameters(url.query)

Now you have a nice params hash that you can play with in any way you see fit - this will depend on your requirements, of course, but my need was something a little like:

RUBY:
  1. route.merge! :search => session[:search] if route[:controller] == "search" and session[:search]

And then you can turn the whole thing back into a url again, simply by using url_for:

RUBY:
  1. SomeThing.do_something_with(url_for(route))

Cheers,
Neil.