Rails Named Routes: Path Vs. URL
Mark Cornick, Former Viget
Article Category:
Posted on
As we all learned in Rails 101, named routes come in two varieties: path, and URL. When should we use each variety?
Let's say we have this entry in a routes.rb file:
map.resources :doohickeys
So, we can refer to doohickeys_path, which returns a relative URI:
link_to 'index of doohickeys', doohickeys_path # => <a href="/doohickeys">index of doohickeys</a>
And we can refer to doohickeys_url, which returns an absolute URI:
link_to 'index of doohickeys', doohickeys_url # => <a href="http://www.example.com/doohickeys">index of doohickeys</a>
So when do you use paths, and when do you use URLs? I had heard that there are two cases when you must use URLs:
- You need to use an absolute URI when linking to an SSL site from a non-SSL site, and vice versa.
- You need to use an absolute URI when creating a redirect (e.g. with
redirect_to
.)
In talking with some fellow developers here at Viget, and at Thoughtbot when I trained there recently, we agreed that the Rails convention seems to be to use URLs in these two cases, and paths in other cases. But why?
The first case is pretty obvious; you need the absolute URI in order to get the https://
prefix for a secure site (and likewise to get the http://
prefix if you need to get back to where you were.) For the second case, you need to dig into the HTTP specification, also known as RFC 2616. In particular, you need to find section 14.30, which defines the Location header that’s returned in a redirect. Here’s the chapter and verse:
The Location response-header field is used to redirect the recipient to a location other than the Request-URI for completion of the request or identification of a new resource. For 201 (Created) responses, the Location is that of the new resource which was created by the request. For 3xx responses, the location SHOULD indicate the server's preferred URI for automatic redirection to the resource. The field value consists of a single absolute URI.
(Emphasis added.) So that’s the answer: we do it this way because the specification says we have to. Since we’re all about conventions in the Rails community, we may as well have our convention follow the spec. Is it critical to do so? Probably not; most modern HTTP clients and servers seem to figure out what you meant if you pass a relative URL in a redirect. But why take the chance when it’s easy to do the right thing?