About the Scope of Default View Helpers
In this article, I’ll explain what scope the methods defined in Rails view helpers apply to,
how to change this scope, and a reasonable step-by-step procedure for safely changing the scope in an existing application.
Methods Defined in Helpers Can Be Called from Any View
For example, suppose you have UsersHelper#display_name defined like this:
# app/helpers/users_helper.rb
module UsersHelper
  def display_name(user)
    "#{user.lastname} #{user.firstname}"
  end
end
This method can be used not only in views rendered by UsersController, but also in views rendered by other controllers:
# app/controllers/posts_controller.rb
class PostsController
  def index
    @posts = Post.all
  end
end
<% # app/views/posts/index.html.erb %>
<% @posts.each do |post| %>
  <p><%= post.content %></p>
  <small><%= display_name(post.user) %></small> <!-- display_name is usable -->
<% end %>
In other words, methods defined in view helpers are basically usable in any view.
You might just accept this as “that’s the spec,” but because the scope is so broad, there are concerns.
Some issues include:
- To confirm that a helper method is unused, you must check the entire application.
- It’s difficult to predict behavior when methods with the same name are defined in different helpers.
Rails provides an option to address such concerns.
  
  
  The config.action_controller.include_all_helpers Option
As noted above, by default Rails controllers load all helpers.
This behavior depends on the setting of config.action_controller.include_all_helpers.
https://guides.rubyonrails.org/configuring.html#config-action-controller-include-all-helpers
Configures whether all view helpers are available everywhere or are scoped to the corresponding controller.
The default value is true.
So, if you set this option in config/application.rb, the behavior changes:
 module Example
   class Application < Rails::Application # Initialize configuration defaults for originally generated Rails version.
     config.load_defaults 8.0
+
+    config.action_controller.include_all_helpers = false
With this setting, a method like display_name defined in UsersHelper
can no longer be called from a view rendered by PostsController:
# app/helpers/users_helper.rb
module UsersHelper
  def display_name(user)
    "#{user.lastname} #{user.firstname}"
  end
end
# app/controllers/posts_controller.rb
class PostsController
  def index
    @posts = Post.all
  end
end
<% # app/views/posts/index.html.erb %>
<% @posts.each do |post| %>
  <p><%= post.content %></p>
  <!-- Cannot be called! -->
  <small><%= display_name(post.user) %></small> <!-- undefined method 'display_name' for ... -->
<% end %>
How Is the Applicable Helper Determined?
Suppose we have the following controller and helper inheritance structure:
app/
├── controllers
│ ├── admin
│ │ ├── application_controller.rb
│ │ └── users_controller.rb
│ ├── application_controller.rb
│ ├── posts_controller.rb
│ └── users_controller.rb
└── helpers
├── admin
│ ├── application_helper.rb
│ └── users_helper.rb
├── application_helper.rb
├── posts_helper.rb
└── users_helper.rb
class ApplicationController < ActionController::Base; end
class UsersController < ApplicationController; end
class PostsController < ApplicationController; end
class Admin::ApplicationController < ApplicationController; end
class Admin::UsersController < Admin::ApplicationController; end
In the context of UsersController, the following helpers are included:
- UsersHelper
- 
ApplicationHelper(always)
This depends on controller inheritance.
UsersController automatically includes UsersHelper, and ApplicationController includes ApplicationHelper.
Thus, UsersController has both UsersHelper and ApplicationHelper methods available.
As another example, in the context of Admin::UsersController, the included helpers are:
- Admin::UsersHelper
- Admin::ApplicationHelper
- ApplicationHelper
This aligns with the inheritance chain:
Admin::UsersHelper, Admin::ApplicationHelper, and then ApplicationHelper.
This behavior is the same as the template lookup inheritance mechanism used for rendering templates and partials:
https://guides.rubyonrails.org/layouts_and_rendering.html#template-inheritance
  
  
  Migrating an Existing Application to include_all_helpers = false
This setting is very useful.
Here’s a migration path for existing applications.
First Step
The first step is, of course, to set config.action_controller.include_all_helpers = false:
 module Example
   class Application < Rails::Application # Initialize configuration defaults for originally generated Rails version.
     config.load_defaults 8.0
+
+    config.action_controller.include_all_helpers = false
With this alone, you’ll get errors in places where helper methods “happened to be available.”
As a temporary measure, include all helpers in ApplicationHelper to maintain existing behavior:
# app/helpers/application_helper.rb
module ApplicationHelper
  include Admin::ApplicationHelper
  include Admin::UsersHelper
  include PostsHelper
  include UsersHelper
end
(In many apps, all controllers ultimately inherit from ApplicationController, so ApplicationHelper is available in every view.)
Narrowing Things Down Gradually
From here, reduce dependencies step by step.
For example, if everything under Admin::\* inherits from Admin::ApplicationController, group them there:
# app/helpers/application_helper.rb
module ApplicationHelper
  include Admin::ApplicationHelper
  include PostsHelper
  include UsersHelper
end
# app/helpers/admin/application_helper.rb
module Admin::ApplicationHelper
  include Admin::UsersHelper
end
Then, remove helpers from ApplicationHelper if they’re only used in a specific controller:
 module ApplicationHelper
   include Admin::ApplicationHelper
-  include PostsHelper
   include UsersHelper
 end
On the other hand, for utility methods used across multiple contexts, move them into ApplicationHelper:
 module ApplicationHelper
   include Admin::ApplicationHelper
-  include UsersHelper
+
+  def very_useful_helper_method(user)
+    #
+  end
 end
 module UsersHelper
-  def very_useful_helper_method(user)
-    #
-  end
 end
By making these adjustments, you can converge toward a scope that is “only available where needed.”
When Helper Methods from Gems Stop Working
This may surface with gems like font-awesome-rails.
That gem provides the view helper method fa_icon.
But when config.action_controller.include_all_helpers = false, you must explicitly include it.
Simply include it in ApplicationHelper, and you’re done.
This makes usage more explicit, which is a good thing for maintainability:
# app/helpers/application_helper.rb
module ApplicationHelper
  include FontAwesome::Rails::IconHelper
end
Summary
- By default, methods defined in view helpers can be called from any controller’s view.
- Setting config.action_controller.include_all_helpers = falserestricts loaded helpers to those corresponding to the controller (and its inheritance chain).
- 
ApplicationHelperis always included regardless of the setting, making it a good place for common methods.
- For migration, the safe path is: “collect everything in ApplicationHelperfirst → then gradually move and reduce.”
Disclaimer
The content in this article was verified with Rails 8.0.2.1,
but the behavior is basically the same in many past versions.
(Strictly speaking, this assumes Rails 3.1 or later, when include_all_helpers was introduced.)
 


 
    
Top comments (0)