Castle and Riders

Secrets of Links in Rails

Rails provides a handy method for creating a link in your views:

link_to "Home Page", "http://gridworlds.com"
=>  <a href="http://gridworlds.com">Home Page</a>

Of course, if this were all the link_to() method did, there would be little reason to use it instead of just typing the HTML directly. This method makes it easy to generate links that tie directly to controllers and actions. For example:

link_to :Edit, :controller => :user, :action => :edit
=>  <a href="/user/edit">Edit</a>

If you leave out the controller, Rails assumes the controller that called the view:

link_to :Edit, :action => :index
=>  <a href="/user">Edit</a>

Conditional Links

The UrlHelper module includes several other methods to make linking easier. Sometimes you need to display a link conditionally. For example, in a navigation menu you may not want to link the active navigation item for the current page. You could always wrap a link in an if/then statement, like this:

if navigation != active
  link_to "FAQ", "/faq"
end

But why use three statements when one will do?

link_to_if navigation != active, "FAQ", "/faq"

Rails includes two other conditional link methods you may find useful: link_to_unless() and link_to_unless_current().

Secret Life of Links

The secret of link_to() is that it uses url_for() to generates these URLs. The url_for() method allows you to generate only a URL without the corresponding <a href=”…”> tag. When would you do this? How about in a JavaScript onclick handler:

<div onclick="window.location = '<%= url_for :action => :edit %>'">
I want this whole div to be clickable
</div>

url_for() also includes a bunch of options for setting the host, protocol, anchor, generating absolute or relative links, etc. Check out the Rails docs for full details.

What About Query Parameters?

Both link_to() and url_for() provide an undocumented way to include additional query parameters in your URLs. While it is easy to include an ID, like this…

link_to "Edit User", :controller => :user, :action => :edit, :id => 12
=>  <a href="/user/edit/12">Edit User</a>

…what if you want to generate a URL with both an ID and separate query parameters? Just tack on additional parameters at the end, like this:

link_to "Edit User", :controller => :user, :action => :edit, :id => 12, :firstname => "Joe", :lastname => "Smith"
=>  <a href="/user/edit/12?firstname=Joe&lastname=Smith">Edit User</a>

There’s one gotcha here: Rails tries to guess which parameters are options for the link_to() or url_for() methods and which should be converted to query parameters. If you aren’t explicitly using {:curley => :brackets} in your method call, Rails may interpret your options as query parameters. Here’s a good example:

link_to :Test1, :controller => :user, :action => :edit, :id => 12, :confirm => "Are you sure?"
=>  <a href="/user/edit/12?confirm=Are+you+sure%3F">Test1</a>

link_to :Test2, { :controller => :user, :action => :edit, :id => 12 }, :confirm => "Are you sure?"
=>  <a href="/user/edit/12" onclick="return confirm('Are you sure?')">Test2</a>

Notice in the first example the :confirm symbol is just another query parameter, while in the second example :confirm is a JavaScript dialog. The only difference between the two is the addition of curly brackets to make the confirm explicit.

Posted on August 24th, 2008 in the Rails category | Permalink
You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.

Leave a Reply

You must be logged in to post a comment.