I have various methods providing default behaviors in the application_helper.rb file of my current project.
These methods are commons to all my controllers but some of them may decide to override this default behavior if necessary.
To do so, they can redefine the methods in their own helper.
Let's say that I have the say_hi method in application_helper.rb :
def say_hi
"Hi from ApplicationController"
end"
If I call it in the views related to my controllers 'Controller1' and 'Controller2', the text "Hi from ApplicationController" will be correctly displayed.
Now, I want to change this greeting message in the pages of Controller1. I can redefine the method say_hi in controller1_helper.rb :
def say_hi
"Hi from Controller1"
end"
Everything works fine.
But now, if I apply the same solution in controller2_helper.rb :
def say_hi
"Hi from Controller2"
end"
The message displayed in the pages of Controller2 will be correct. But on the other hand, pages of Controller1 will display "Hi from Controller2" instead of "Hi from Controller1".
This is a strange behavior, I was not excepting a such result.
This issue is caused by this sentence in your ApplicationController :
helper :all
The goal of this method is to include all custom helpers in all views.
All methods of all helpers will then be included in the current view.
Controller2 is the last one in the list (alphabetical order) so it is the last included and his 'say_hi' method will be used.
You can open the file actionpack/lib/action_controller/helpers.rb to see how it works :
def helper(*args, &block)
args.flatten.each do |arg|
case arg
when Module
add_template_helper(arg)
when :all
helper(all_application_helpers)
when String, Symbol
file_name = arg.to_s.underscore + '_helper'
class_name = file_name.camelize
begin
require_dependency(file_name)
rescue LoadError => load_error
requiree = / -- (.*?)(.rb)?$/.match(load_error.message).to_a[1]
if requiree == file_name
msg = "Missing helper file helpers/#{file_name}.rb"
raise LoadError.new(msg).copy_blame!(load_error)
else
raise
end
end
add_template_helper(class_name.constantize)
else
raise ArgumentError, "helper expects String, Symbol, or Module argument (was: #{args.inspect})"
end
end
def all_application_helpers
extract = /^#{Regexp.quote(helpers_dir)}\/?(.*)_helper.rb$/
Dir["#{helpers_dir}/**/*_helper.rb"].map { |file| file.sub extract, '\1' }
end
When the helper method is called with the :all parameter, it will re-invoke itself with the result of all_application_helpers as a parameter.
This method will return an array containing the names of all helpers defined in the app/helpers folder (in my case, 'application', 'controller1' and 'controller2').
The new call to the helper method will then browse each name and include the corresponding helper.
So I removed the helper :all line in my ApplicationController and everything worked fine.
But I'm wondering on the interest of this method.
Why would the methods associated to Controller2 be available in Controller1?
I have no problem against the existence of this method but it's for me a mistake to include it by default in a fresh new Rails application.
Add a comment
0 comment for this article