I was digging in some old Basecamp code today while working on a new feature and I ran into this bit of view code:
<div class="rss">
<%= rss_link :icon %>
<p><%= rss_link "Project RSS feed" %></p>
</div>
This code renders an RSS icon wrapped in a link and a text link beside it:
I wanted to add a class to the linked RSS icon. If the template used the standard Rails link_to
helper to render the linked image I would know how to provide the class with an options hash. But rss_link
isn’t a standard helper, so I had to dig up the definition to see what’s possible. It wasn’t very pretty:
def rss_link(body, options={})
if body == :icon
body = image_tag("feed-icon-14x14.png", :size => "14x14", :alt => "RSS Feed",
:border => "0", :align => "absmiddle")
end
link_to(body, { :controller => "project", :action => "rss_confirm",
:return_to => request.request_uri }, options)
end
It turned out we were using a single helper to render either a text link or a linked icon for the RSS feed depending on the ‘body’ param. It works fine, but I would have never been able to guess how it works without looking inside the method definition. Now I can see that it is possible to pass an options hash, but I had to look to find that out.
It would have been better in this case to use the standard link_to
in the template and delegate the truly unique stuff to helper methods. The unique bits that I don’t want to repeat are the long url_for
hash and the image tag params. Here’s a refactoring that splits the helper into two methods to return only those special parts:
def rss_path
{ :controller => "project", :action => "rss_confirm",
:return_to => request.request_uri }
end
def rss_icon
image_tag("feed-icon-14x14.png", :alt => "RSS Feed", :class => "rss_icon")
end
These helpers allow me to stick with link_to
, which is a helper that I and my team already understand:
<div class="rss">
<%= link_to rss_icon, rss_path, :class => 'image' %>
<p><%= link_to "Project RSS feed", rss_path %></p>
</div>
It’s much easier to tell at a glance what this code is doing and it’s easier to make changes because the link_to
helper is standard.
The next time we want to change this bit of view code, we won’t have to dig into the helper to check if it takes an options hash. It’s clear from the call to link_to
that we’re simply providing method calls as params. I hope this tip helps to make your view code a bit more readable and more predictable to maintain.