Before I start I just want to make it clear that I know the arguments against using url_for in models and even in rake tasks. Sometimes however it makes sense to use_url for in a rake task. In my case I am trying to query another site’s api which requires the URI of the page on my site that I want to gather information about.
The approach in Rails 2.x
task :collect_stats => :environment do include ActionController::UrlWriter default_url_options[:host] = 'www.example.com' url = url_for(:controller => 'foo', :action => 'bar') end
Notice that because there is no current request you have to specify the
default_url_options[:host]
as the helper has no idea what the host will be otherwise.
Doing the same thing in Rails 3
The following code does the same thing in Rails 3.
task :collect_stats => :environment do include ActionDispatch::Routing::UrlFor #include ActionController::UrlFor #requires a request object include ActionController::PolymorphicRoutes include Rails.application.routes.url_helpers default_url_options[:host] = 'www.example.com' url = url_for(post) end
There are two key points to notice here.
- The first is that I have included ActionDispatch::Routing::UrlFor rather than ActionController::UrlFor. The latter requires a request object and will attempt to automatically fill in the host name. Since we are in a rake task there is no request and the method will fail.
- The second thing is that I have also included two additional includes. The will allow you to work with polymorphic routes and named routes, giving a bit more flexibility.
Just a short snippet that might be of use to people but if there are any improvements out there then please let me know and I will update this. You can of course hard code the routes but there are scenarios where it makes much more sense to make use of the helpers provided, especially when using polymorphic routes.
Update: 08/06/2010
In the comments Jakub has stated that in the latest version of Rails you don’t need to include the polymorphic routes.
include ActionController::PolymorphicRoutes
It seems you only need to include Rails.application.routes.url_helpers (at least in the latest version).
@Jakub thanks, does that give you the polymorphic routes too or just allow you to use url_for? Although I have this working in the latest beta I haven’t actually looked into it just checked that it worked.
Looks like both – I was looking specifically for polymorphic routes, but it seems url_for also works.
Brilliant I will update the article to say that you don’t need to include polymorphic routes. Thanks!
Just check before if it works for you too ;)
Nice – but what if I wanted to get access to named routes rather than url_for ?
I think I found it – just
include ActionController::UrlWriter
and all your named routes suddenly exist in your rake task.