link_to_if
link_to_if(condition, name, options = {}, html_options = {}, &block)
public
Creates a link tag of the given name using a URL created by the set of options if condition is true, otherwise only the name is returned. To specialize the default behavior, you can pass a block that accepts the name or the full argument list for link_to_unless (see the examples in link_to_unless).
Examples
<%= link_to_if(@current_user.nil?, "Login", { :controller => "sessions", :action => "new" }) %> # If the user isn't logged in... # => <a href="/sessions/new/">Login</a> <%= link_to_if(@current_user.nil?, "Login", { :controller => "sessions", :action => "new" }) do link_to(@current_user.login, { :controller => "accounts", :action => "show", :id => @current_user }) end %> # If the user isn't logged in... # => <a href="/sessions/new/">Login</a> # If they are logged in... # => <a href="/accounts/show/3">my_username</a>
link_to_if for named routes
Back before named routes we used to say things like:
<%= link_to_if message.user, 'Poster', :controller => 'users', :action => 'show', :id => message.user %>
This would make the text “Poster” only link if message has a user. But with named routes this has become more complicated. Our first try is something like:
<%= link_to_if message.user, 'Poster', user_path(message.user) %>
Although this looks nice it causes an error since the path is generated prior to the condition not after the condition like using a hash is done. To get around this problem I have found two solutions:
-
If you are linking to the “show” path then you can just pass the object. This will force the path to not be generated until after the condition (like a hash is done). For example:
<%= link_to_if message.user, 'Poster', message.user %>
-
The previous workaround works great if you want to link to the show action. But what if you want to link to another action (say the edit action). In this case the best way I have found is to use the hash_for* helpers generated with the routing resource. So:
<%= link_to message.user, 'Poster', hash_for_edit_user_path(:id => message.user) %>
A little more awkward than the previous workaround but it is the best I can come up with. Any other suggestions (other than going back to manually typing the hash)?
link to nothing if link_to_if condition is false
When the link_to_if condition is false you can get this helper to display nothing by doing something like this
<%= link_to_if(message.user, 'Poster', message.user){} %>
^ That will display nothing if message.user does not exist.
Outputs name even if condition is false
Please note that if the condition is false, link_to_if will still output the name given as a plain text (as documented above). If you want nothing printed at all, you’ll have to stay with the old and trusty:
link_to "Login", ... if @current_user.nil?
link_to_if when URL helpers will throw an exception when condition fails
You can use an array to build a URL instead of a URL helper (e.g. edit_admin_user_path(event.user), which would fail when an event has no user:
link_to_if event.user, event.user_name, [:edit, :admin, event.user]
If condition is false, options hash is ignored
Here, the class will be ignored:
<%= link_to_if false, 'Home', root_path, class: 'link' %> #=> Home
Outputs name even if condition is false
Please note that if the condition is false, link_to_if will still output the name given as a plain text (as documented above). If you want nothing printed at all, you’ll have to stay with the old and trusty:
link_to "Login", ... if @current_user.nil?
Passing a block does not behave as expected
When the condition is true, the block is not rendered:
<%= link_to_if true, users_path, {}, {} do %> <i class='fa fa-star'></i> <% end %>
renders:
<a href="/users">/users</a>
But if the condition is false, the block will render:
<%= link_to_if false, users_path, {}, {} do %> <i class='fa fa-star'></i> <% end %>
renders:
<i class='fa fa-star'></i>