Many Rails applications have this basic structure in their helpers folder:
1 2 3 4 5 6 7 8 9 10 11 |
application_helper.rb accounts_helper.rb audits_helper.rb comments_helper.rb images_helper.rb orders_helper.rb posts_helper.rb sessions_helper.rb users_helper.rb ... etc. |
The most important file, as we all know, is application_helper.rb, because this is where code goes to die. It’s often a few hundred lines of randomly added, unrelated methods. This is a confusing, scary place for methods to be. Here’s a few tips for rescuing them:
What’s that noise?
Most projects use script/generate to make their controllers. This leaves a ton of empty helper files. Remove them to better focus on the task at hand:
1 2 |
hg remove accounts_helper.rb audits_helper.rb images_helper.rb ... |
Usually this will prune the list down to two or three files.
Farewell, application_helper.rb
The easiest way to clean up the ApplicationHelper module is to remove it. This is a great way to ensure methods don’t stay there, or get inserted in the future. But, if they don’t belong in ApplicationHelper, where’s the best place for them?
1. Remove fake helpers
Helpers are markup generators. If they’re not involved in generating markup, they’re not helpers and can be pushed into a model:
helpers/application_helper.rb1 2 3 4 5 6 |
module ApplicationHelper def birthday_in_words(child, prefix = 'born') "(#{prefix} #{child.birthday_in_words})" if child.birthday? end end |
1 2 3 4 5 6 |
class Child < ActiveRecord::Base def birthday_in_words(prefix = 'born') "(#{prefix} #{birthday})" if birthday? end end |
Unfortunately Rails relies on this ambigious ‘helper’ naming convention internally, making it tricky to change the naming in your own application. (I find the concept of a helper to be… unhelpful, and will be referring to them as ‘markup generators’ for the rest of this post.)
2. Separate into logical units
By default, Rails makes all markup generators available to any view via helper :all. The relationship between a model and markup generation tends to be incidental, and script/generate’s ‘ModelNameHelper’ convention is a bit sketchy. Better to name it like anything else, so a module that generates, say, HTML for tables, gets named TableHelper.
1 2 3 4 5 6 7 8 9 10 |
module TableHelper def default_sort_column(title, direction) ... end def sort_column(title, direction) ... end end |
Better yet, if the generation starts getting complex, take a page from one of Ryan Bate’s screencasts and turn it into a class
3. Test!
Well organized code is great. Tested, well organized code? Even better!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
require File.join(File.dirname(__FILE__), '..', 'test_helper') require File.join('action_view', 'test_case') class AlexaThumbnailHelperTest < ActionView::TestCase context "Generating Alexa image tags" do setup do @url = 'http://ted.com' @alexa_image_tag_html = %(<img src="http://ast.amazonaws.com/?...=#{@image_url}"/>) end should "return the image tag as html" do assert_equal @alexa_image_tag_html, alexa_image_tag(@url) end end end |
And a method
On a related note, in a few cases it’s useful to allow your templates access to controller methods. Rails provides helper_method to handle this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
class ApplicationController < ActionController::Base # Give views access to these methods: helper_method :current_user, :logged_in? protected def current_user ... end def logged_in? ... end end |

” hg remove” was something new to me. Learn some thing new everyday . Nice article.
I usually allow new methods to live in application_helper until there are 2-3 related methods that could be extracted into a separate helper.
Using a ton of helper modules with 1 method each is counterproductive since i always have to remember if the xx method was in abc_helper or bcd_helper. It also reduces rework since i do not have to name/create/create-testfile for the new helper, which often would change its name or join with someone else faster than i can say “oh no, we wanted this to look like…”
Summary: Let the lonely live in application helper, extract groups of 2-3
Great writeup. Although I do create new helper modules like your TableHelper module, I never really remove the empty ones – I’ll certainly start now. No hg on Windows though sadly :(
You’re also making me feel bad about not testing my helpers. I test everything else so they must be feeling a little left out. My shame has almost reached the threshold where I’ll start giving them some testing love… almost :)
FYI:
hg removeis a Mercurial command. It’d be like doingsvn rmorgit rm.I plead guilty to some of the code in this article, but I still like the idea of one honking big application_helper.rb. Why? I like to know where to find the methods! (I guess this would be a moot point if I used a TAGS file but I don’t.)
Eric’s got a good point about non-markup helpers though. Those don’t belong in the helper files. They should be in the model.
I’m not so sure about this. Helpers are abstractions of view logic, and don’t necessarily generate markup. There’s a reason why methods like
time_ago_in_wordsare helper methods and not instance methods onTime.Child#birthday_in_wordstruly does belong in a helper…just not inApplicationHelper, if possible.So do you see this as encapsulation vs DRY?
Interesting – DHH recommended this exact thing at his RailsConf Europe keynote today. Ditch your ApplicationHelper, or that methods shouldn’t stay in the module long-term.