I loathe helper :all
. What’s the point of nicely divided helper modules if they’re all injected into same namespace, overwriting each other at random? I like to write reusable helpers that individual controllers can use by implementing their version of a foo
method. I see no reason why two completely unrelated helper modules couldn’t both has a display_help_text
method. helper :all
prevents both of these and creates situations where you can accidentally overwrite a helper method in a completely different part of your application.
Obviously not everyone agrees with me because Rails continues to move in the other direction. Once upon a time, a bare controller only pulled in its default helper (ie Bar::FooController
gets Bar::FooHelper
) and the helpers for its ancestors. Later, the default application skeleton added helper :all
to ApplicationController
but this was still an opt in scheme. With Rails 3 it is an opt out scheme: you have to put clear_helpers
in a controller to clear out the helpers Rails includes automatically for it.
Update:
As of Rails 3.1, you can do config.action_controller.include_all_helpers = false
to escape this madness.
View Specs
Rspec tries to do the right thing - if you poke into view_example_group.rb
in rspec-rails you can see it determining the default helper class and including that and ApplicationHelper
into the view object. Unforunately it also includes controller._helpers
. This controller isn’t an instance of the controller class that will use the view - it’s an instance of ActionView::TestCase::TestController
, so has Rails’ default of the full set of helpers, irrespective of how the controller in the app is configured.
The first step is of course calling clear_helpers
on ActionView::TestCase::TestController
but if your application has helper modules that are used by multiple controllers then some of your view specs may start to fail. You could of course add those helpers to the view from your before(:each)
blocks but that is a slightly nasty piece of duplication: you’ve already specified once which helpers should be used. More dangerously you could develop a situation where your view specs pass because they specify one set of helpers but your app fails because your controllers specify a different set.
To remedy this I’ve got the following in one of my apps:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
|
This works out what controller class the view will normally be used with, for admin/foo/bar.html.haml this would be Admin::FooController
and uses the helpers that controller would use normally.
A call to config.include(ViewHelpersSpecHelper)
in my RSpec.configure
block ensures that this module gets included everywhere relevant.
Cells
This starts to break down for partials that are rendered by multiple different controllers or for shared ones that don’t have a natural controller they can be tested with. This is perhaps the one thing that helper :all
doesn’t make worse, since it does mean that a given view is always rendered with the same set of helper functions available. If you do have such units of view and helper code, the cells library is well worth a look.