The Difference Between Url_for and Polymorphic_url

| Comments

url_for is a great Rails helper that returns a URL that has been rewritten according to the options hash passed to it and defined routes. Rails passes all the keys in the options hash to the routing module. There are a few exceptions, including (but not limited to) :only_path, :trailing_slash, and :host. For a full list please see the docs here.

        <%= url_for :controller => "recipes", :action => "show", :id => 1 %>

This would generate a url that looks like this:’http://domain.com/recipes/show/10’

But let’s say you were trying to generate a URL for a polymorphic object, or a nested object, or you just want the absolute path. Let’s take an image object. My image class is polymorphic, and thus belongs to every model as imageable.

        <%= url_for @image :only_path => false %>

Setting :only_path to false generates the full url instead of just the relative path. url_for is really like path_for. You have to pass it an additional argument to return the full URL. But that example returns an error: Wrong number of arguments(2 for 1). Essentially in the example above, you’re passing two arguments– an object and a hash.

But, if you only pass one argument, the object…

            <%=url_for @image %>

This produces a relative path to the image. When you pass an ActiveRecord object to url_for, it causes a lookup on the image class, essentially calling @image.to_params, and use image_path to generate the path.

So how then do you get the full URL with the domain name without doing some hackey "http://mydomain.com" + < my_query_string_generated_from_url_for > ?

This is where polymorphic_url comes in. polymorphic_url is a Rails helper method for calling a named route. It also provides support for nested resources. This helper method is designed to return a full URL, instead of just the relative path, without passing any arguments. If you did want the relative path, polymorphic_path does just that.

So let’s say we’re on an image record

        <%= polymorphic_url(@image) %>

That would be the same as calling image_url(@image). Rails would return “http://mydomain.com/images/1”

So now say you want to access the images from the recipes. This is where the nested support of polymorphic_url comes into play.

        <%= polymorphic_url([recipe, image])%>

This would return “http://mydomain.com/recipes/1/images/1”

So when do you use these handy helpers?A path should always be used unless you’re doing a full redirect.

Additional Resources
1. The Docs for url_for.
2. The Docs for polymorphic_url

Comments