helper的加载
想观察下helper是如何加载的,于是加个断点
From: /home/z/test_rails/depot/app/helpers/application_helper.rb @ line 3 :
1: binding.pry
2:
=> 3: module ApplicationHelper
4: def something_in_cart?
5: @cart and not @cart.line_items.empty?
6: end
7: end
[1] pry(main)> _bsi_
=> {0=>#<binding:70142525638460 object#<top="" (required)=""> /home/z/test_rails/depot/app/helpers/application_helper.rb:1>,
1=>#<binding:70142997020320 activesupport::dependencies.block="" in="" load_file="" home="" z="" .rbenv="" versions="" 2.4.0="" lib="" ruby="" gems="" 2.4.0="" gems="" activesupport-5.0.2="" lib="" active_support="" dependencies.rb:477="">,
2=>#<binding:70142525785720 activesupport::dependencies.new_constants_in="" home="" z="" .rbenv="" versions="" 2.4.0="" lib="" ruby="" gems="" 2.4.0="" gems="" activesupport-5.0.2="" lib="" active_support="" dependencies.rb:662="">,
3=>#<binding:70142525861020 activesupport::dependencies.load_file="" home="" z="" .rbenv="" versions="" 2.4.0="" lib="" ruby="" gems="" 2.4.0="" gems="" activesupport-5.0.2="" lib="" active_support="" dependencies.rb:476="">,
4=>#<binding:70142996807940 activesupport::dependencies.block="" in="" require_or_load="" home="" z="" .rbenv="" versions="" 2.4.0="" lib="" ruby="" gems="" 2.4.0="" gems="" activesupport-5.0.2="" lib="" active_support="" dependencies.rb:375="">,
5=>#<binding:70142996741920 activesupport::dependencies.block="" in="" load_interlock="" home="" z="" .rbenv="" versions="" 2.4.0="" lib="" ruby="" gems="" 2.4.0="" gems="" activesupport-5.0.2="" lib="" active_support="" dependencies.rb:37="">,
6=>#<binding:70142526081600 activesupport::dependencies::interlock#block="" in="" loading="" home="" z="" .rbenv="" versions="" 2.4.0="" lib="" ruby="" gems="" 2.4.0="" gems="" activesupport-5.0.2="" lib="" active_support="" dependencies="" interlock.rb:12="">,
7=>#<binding:70142996611320 activesupport::concurrency::sharelock#exclusive="" home="" z="" .rbenv="" versions="" 2.4.0="" lib="" ruby="" gems="" 2.4.0="" gems="" activesupport-5.0.2="" lib="" active_support="" concurrency="" share_lock.rb:150="">,
8=>#<binding:70142996431800 activesupport::dependencies::interlock#loading="" home="" z="" .rbenv="" versions="" 2.4.0="" lib="" ruby="" gems="" 2.4.0="" gems="" activesupport-5.0.2="" lib="" active_support="" dependencies="" interlock.rb:11="">,
9=>#<binding:70142996261040 activesupport::dependencies.load_interlock="" home="" z="" .rbenv="" versions="" 2.4.0="" lib="" ruby="" gems="" 2.4.0="" gems="" activesupport-5.0.2="" lib="" active_support="" dependencies.rb:37="">,
10=>#<binding:70142996019940 activesupport::dependencies.require_or_load="" home="" z="" .rbenv="" versions="" 2.4.0="" lib="" ruby="" gems="" 2.4.0="" gems="" activesupport-5.0.2="" lib="" active_support="" dependencies.rb:358="">,
11=>#<binding:70142995857360 activesupport::dependencies.depend_on="" home="" z="" .rbenv="" versions="" 2.4.0="" lib="" ruby="" gems="" 2.4.0="" gems="" activesupport-5.0.2="" lib="" active_support="" dependencies.rb:336="">,
12=>#<binding:70142995630260 applicationcontroller.require_dependency="" home="" z="" .rbenv="" versions="" 2.4.0="" lib="" ruby="" gems="" 2.4.0="" gems="" activesupport-5.0.2="" lib="" active_support="" dependencies.rb:252="">,
13=>#<binding:70142995556120 applicationcontroller.block="" in="" modules_for_helpers="" home="" z="" .rbenv="" versions="" 2.4.0="" lib="" ruby="" gems="" 2.4.0="" gems="" actionpack-5.0.2="" lib="" abstract_controller="" helpers.rb:150="">,
14=>#<binding:70142995421940 applicationcontroller.modules_for_helpers="" home="" z="" .rbenv="" versions="" 2.4.0="" lib="" ruby="" gems="" 2.4.0="" gems="" actionpack-5.0.2="" lib="" abstract_controller="" helpers.rb:145="">,
15=>#<binding:70142995222820 applicationcontroller.modules_for_helpers="" home="" z="" .rbenv="" versions="" 2.4.0="" lib="" ruby="" gems="" 2.4.0="" gems="" actionpack-5.0.2="" lib="" action_controller="" metal="" helpers.rb:93="">,
16=>#<binding:70142995114560 applicationcontroller.helper="" home="" z="" .rbenv="" versions="" 2.4.0="" lib="" ruby="" gems="" 2.4.0="" gems="" actionpack-5.0.2="" lib="" abstract_controller="" helpers.rb:109="">,
17=>#<binding:70142990394940 applicationcontroller.default_helper_module!="" home="" z="" .rbenv="" versions="" 2.4.0="" lib="" ruby="" gems="" 2.4.0="" gems="" actionpack-5.0.2="" lib="" abstract_controller="" helpers.rb:187="">,
18=>#<binding:70142990015780 applicationcontroller.block="" in="" inherited="" home="" z="" .rbenv="" versions="" 2.4.0="" lib="" ruby="" gems="" 2.4.0="" gems="" actionpack-5.0.2="" lib="" abstract_controller="" helpers.rb:36="">,
19=>#<binding:70142989367180 actioncontroller::base.inherited="" home="" z="" .rbenv="" versions="" 2.4.0="" lib="" ruby="" gems="" 2.4.0="" gems="" actionpack-5.0.2="" lib="" abstract_controller="" helpers.rb:36="">,
20=>#<binding:70142988773160 actioncontroller::base.inherited="" home="" z="" .rbenv="" versions="" 2.4.0="" lib="" ruby="" gems="" 2.4.0="" gems="" actionview-5.0.2="" lib="" action_view="" layouts.rb:217="">,
21=>#<binding:70142988435320 actioncontroller::base.inherited="" home="" z="" .rbenv="" versions="" 2.4.0="" lib="" ruby="" gems="" 2.4.0="" gems="" actionpack-5.0.2="" lib="" action_controller="" metal="" rendering.rb:23="">,
22=>#<binding:70142985277140 actioncontroller::base.inherited="" home="" z="" .rbenv="" versions="" 2.4.0="" lib="" ruby="" gems="" 2.4.0="" gems="" actionpack-5.0.2="" lib="" action_controller="" metal="" params_wrapper.rb:224="">,
23=>#<binding:70142984428220 actioncontroller::base.block="" (2="" levels)="" in="" with="" home="" z="" .rbenv="" versions="" 2.4.0="" lib="" ruby="" gems="" 2.4.0="" gems="" actionpack-5.0.2="" lib="" abstract_controller="" railties="" routes_helpers.rb:7="">,
24=>#<binding:70142981935200 actioncontroller::base.inherited="" home="" z="" .rbenv="" versions="" 2.4.0="" lib="" ruby="" gems="" 2.4.0="" gems="" actionpack-5.0.2="" lib="" action_controller="" railties="" helpers.rb:5="">,
25=>#<binding:70142976438520 object#<top="" (required)=""> /home/z/test_rails/depot/app/controllers/application_controller.rb:1>,
26=>#<binding:70142526053680 activesupport::dependencies.block="" in="" load_file="" home="" z="" .rbenv="" versions="" 2.4.0="" lib="" ruby="" gems="" 2.4.0="" gems="" activesupport-5.0.2="" lib="" active_support="" dependencies.rb:477="">,
27=>#<binding:70142525963520 activesupport::dependencies.new_constants_in="" home="" z="" .rbenv="" versions="" 2.4.0="" lib="" ruby="" gems="" 2.4.0="" gems="" activesupport-5.0.2="" lib="" active_support="" dependencies.rb:662="">,
28=>#<binding:70142525848780 activesupport::dependencies.load_file="" home="" z="" .rbenv="" versions="" 2.4.0="" lib="" ruby="" gems="" 2.4.0="" gems="" activesupport-5.0.2="" lib="" active_support="" dependencies.rb:476="">,
29=>#<binding:70142525742220 activesupport::dependencies.block="" in="" require_or_load="" home="" z="" .rbenv="" versions="" 2.4.0="" lib="" ruby="" gems="" 2.4.0="" gems="" activesupport-5.0.2="" lib="" active_support="" dependencies.rb:375="">,
30=>#<binding:70142525643900 activesupport::dependencies.block="" in="" load_interlock="" home="" z="" .rbenv="" versions="" 2.4.0="" lib="" ruby="" gems="" 2.4.0="" gems="" activesupport-5.0.2="" lib="" active_support="" dependencies.rb:37="">,
31=>#<binding:70142525545500 activesupport::dependencies::interlock#block="" in="" loading="" home="" z="" .rbenv="" versions="" 2.4.0="" lib="" ruby="" gems="" 2.4.0="" gems="" activesupport-5.0.2="" lib="" active_support="" dependencies="" interlock.rb:12="">,
32=>#<binding:70142525446900 activesupport::concurrency::sharelock#exclusive="" home="" z="" .rbenv="" versions="" 2.4.0="" lib="" ruby="" gems="" 2.4.0="" gems="" activesupport-5.0.2="" lib="" active_support="" concurrency="" share_lock.rb:150="">,
33=>#<binding:70142525361420 activesupport::dependencies::interlock#loading="" home="" z="" .rbenv="" versions="" 2.4.0="" lib="" ruby="" gems="" 2.4.0="" gems="" activesupport-5.0.2="" lib="" active_support="" dependencies="" interlock.rb:11="">,
34=>#<binding:70142525239600 activesupport::dependencies.load_interlock="" home="" z="" .rbenv="" versions="" 2.4.0="" lib="" ruby="" gems="" 2.4.0="" gems="" activesupport-5.0.2="" lib="" active_support="" dependencies.rb:37="">,
35=>#<binding:70142525138400 activesupport::dependencies.require_or_load="" home="" z="" .rbenv="" versions="" 2.4.0="" lib="" ruby="" gems="" 2.4.0="" gems="" activesupport-5.0.2="" lib="" active_support="" dependencies.rb:358="">,
36=>#<binding:70142525025400 activesupport::dependencies.load_missing_constant="" home="" z="" .rbenv="" versions="" 2.4.0="" lib="" ruby="" gems="" 2.4.0="" gems="" activesupport-5.0.2="" lib="" active_support="" dependencies.rb:511="">,
37=>#<binding:70142524939660 object.const_missing="" home="" z="" .rbenv="" versions="" 2.4.0="" lib="" ruby="" gems="" 2.4.0="" gems="" activesupport-5.0.2="" lib="" active_support="" dependencies.rb:203="">,
38=>#<binding:70142524828120 object#<top="" (required)=""> /home/z/test_rails/depot/app/controllers/store_controller.rb:1>,
39=>#<binding:70142524682320 activesupport::dependencies.block="" in="" load_file="" home="" z="" .rbenv="" versions="" 2.4.0="" lib="" ruby="" gems="" 2.4.0="" gems="" activesupport-5.0.2="" lib="" active_support="" dependencies.rb:477="">,
40=>#<binding:70142524647060 activesupport::dependencies.new_constants_in="" home="" z="" .rbenv="" versions="" 2.4.0="" lib="" ruby="" gems="" 2.4.0="" gems="" activesupport-5.0.2="" lib="" active_support="" dependencies.rb:662="">,
41=>#<binding:70142524575880 activesupport::dependencies.load_file="" home="" z="" .rbenv="" versions="" 2.4.0="" lib="" ruby="" gems="" 2.4.0="" gems="" activesupport-5.0.2="" lib="" active_support="" dependencies.rb:476="">,
42=>#<binding:70142524494820 activesupport::dependencies.block="" in="" require_or_load="" home="" z="" .rbenv="" versions="" 2.4.0="" lib="" ruby="" gems="" 2.4.0="" gems="" activesupport-5.0.2="" lib="" active_support="" dependencies.rb:375="">,
43=>#<binding:70142524409620 activesupport::dependencies.block="" in="" load_interlock="" home="" z="" .rbenv="" versions="" 2.4.0="" lib="" ruby="" gems="" 2.4.0="" gems="" activesupport-5.0.2="" lib="" active_support="" dependencies.rb:37="">,
44=>#<binding:70142524308840 activesupport::dependencies::interlock#block="" in="" loading="" home="" z="" .rbenv="" versions="" 2.4.0="" lib="" ruby="" gems="" 2.4.0="" gems="" activesupport-5.0.2="" lib="" active_support="" dependencies="" interlock.rb:12="">,
45=>#<binding:70142524258380 activesupport::concurrency::sharelock#exclusive="" home="" z="" .rbenv="" versions="" 2.4.0="" lib="" ruby="" gems="" 2.4.0="" gems="" activesupport-5.0.2="" lib="" active_support="" concurrency="" share_lock.rb:150="">,
46=>#<binding:70142524085460 activesupport::dependencies::interlock#loading="" home="" z="" .rbenv="" versions="" 2.4.0="" lib="" ruby="" gems="" 2.4.0="" gems="" activesupport-5.0.2="" lib="" active_support="" dependencies="" interlock.rb:11="">,
47=>#<binding:70142523974600 activesupport::dependencies.load_interlock="" home="" z="" .rbenv="" versions="" 2.4.0="" lib="" ruby="" gems="" 2.4.0="" gems="" activesupport-5.0.2="" lib="" active_support="" dependencies.rb:37="">,
48=>#<binding:70142523875140 activesupport::dependencies.require_or_load="" home="" z="" .rbenv="" versions="" 2.4.0="" lib="" ruby="" gems="" 2.4.0="" gems="" activesupport-5.0.2="" lib="" active_support="" dependencies.rb:358="">,
49=>#<binding:70142523766560 activesupport::dependencies.load_missing_constant="" home="" z="" .rbenv="" versions="" 2.4.0="" lib="" ruby="" gems="" 2.4.0="" gems="" activesupport-5.0.2="" lib="" active_support="" dependencies.rb:511="">,
50=>#<binding:70142523602100 object.const_missing="" home="" z="" .rbenv="" versions="" 2.4.0="" lib="" ruby="" gems="" 2.4.0="" gems="" activesupport-5.0.2="" lib="" active_support="" dependencies.rb:203="">,
51=>#<binding:70142523557000 activesupport::inflector.block="" in="" constantize="" home="" z="" .rbenv="" versions="" 2.4.0="" lib="" ruby="" gems="" 2.4.0="" gems="" activesupport-5.0.2="" lib="" active_support="" inflector="" methods.rb:268="">,
52=>#<binding:70142523471880 activesupport::inflector.constantize="" home="" z="" .rbenv="" versions="" 2.4.0="" lib="" ruby="" gems="" 2.4.0="" gems="" activesupport-5.0.2="" lib="" active_support="" inflector="" methods.rb:266="">,
53=>#<binding:70142523367100 activesupport::dependencies::classcache#get="" home="" z="" .rbenv="" versions="" 2.4.0="" lib="" ruby="" gems="" 2.4.0="" gems="" activesupport-5.0.2="" lib="" active_support="" dependencies.rb:583="">,
54=>#<binding:70142523290820 activesupport::dependencies.constantize="" home="" z="" .rbenv="" versions="" 2.4.0="" lib="" ruby="" gems="" 2.4.0="" gems="" activesupport-5.0.2="" lib="" active_support="" dependencies.rb:614="">,
55=>#<binding:70142523212960 actiondispatch::request#controller_class="" home="" z="" .rbenv="" versions="" 2.4.0="" lib="" ruby="" gems="" 2.4.0="" gems="" actionpack-5.0.2="" lib="" action_dispatch="" http="" request.rb:81="">,
56=>#<binding:70142523060760 actiondispatch::routing::routeset::dispatcher#controller="" home="" z="" .rbenv="" versions="" 2.4.0="" lib="" ruby="" gems="" 2.4.0="" gems="" actionpack-5.0.2="" lib="" action_dispatch="" routing="" route_set.rb:44="">,
57=>#<binding:70142523018800 actiondispatch::routing::routeset::dispatcher#serve="" home="" z="" .rbenv="" versions="" 2.4.0="" lib="" ruby="" gems="" 2.4.0="" gems="" actionpack-5.0.2="" lib="" action_dispatch="" routing="" route_set.rb:30="">,
58=>#<binding:70142522925400 actiondispatch::journey::router#block="" in="" serve="" home="" z="" .rbenv="" versions="" 2.4.0="" lib="" ruby="" gems="" 2.4.0="" gems="" actionpack-5.0.2="" lib="" action_dispatch="" journey="" router.rb:39="">,
59=>#<binding:70142522801580 actiondispatch::journey::router#serve="" home="" z="" .rbenv="" versions="" 2.4.0="" lib="" ruby="" gems="" 2.4.0="" gems="" actionpack-5.0.2="" lib="" action_dispatch="" journey="" router.rb:26="">,
60=>#<binding:70142522699960 actiondispatch::routing::routeset#call="" home="" z="" .rbenv="" versions="" 2.4.0="" lib="" ruby="" gems="" 2.4.0="" gems="" actionpack-5.0.2="" lib="" action_dispatch="" routing="" route_set.rb:725="">,
61=>#<binding:70142522594200 rack::etag#call="" home="" z="" .rbenv="" versions="" 2.4.0="" lib="" ruby="" gems="" 2.4.0="" gems="" rack-2.0.1="" lib="" rack="" etag.rb:25="">,
# ...............</binding:70142522594200></binding:70142522699960></binding:70142522801580></binding:70142522925400></binding:70142523018800></binding:70142523060760></binding:70142523212960></binding:70142523290820></binding:70142523367100></binding:70142523471880></binding:70142523557000></binding:70142523602100></binding:70142523766560></binding:70142523875140></binding:70142523974600></binding:70142524085460></binding:70142524258380></binding:70142524308840></binding:70142524409620></binding:70142524494820></binding:70142524575880></binding:70142524647060></binding:70142524682320></binding:70142524828120></binding:70142524939660></binding:70142525025400></binding:70142525138400></binding:70142525239600></binding:70142525361420></binding:70142525446900></binding:70142525545500></binding:70142525643900></binding:70142525742220></binding:70142525848780></binding:70142525963520></binding:70142526053680></binding:70142976438520></binding:70142981935200></binding:70142984428220></binding:70142985277140></binding:70142988435320></binding:70142988773160></binding:70142989367180></binding:70142990015780></binding:70142990394940></binding:70142995114560></binding:70142995222820></binding:70142995421940></binding:70142995556120></binding:70142995630260></binding:70142995857360></binding:70142996019940></binding:70142996261040></binding:70142996431800></binding:70142996611320></binding:70142526081600></binding:70142996741920></binding:70142996807940></binding:70142525861020></binding:70142525785720></binding:70142997020320></binding:70142525638460>
如无意外,应该是53到56之间的动作会加载controller,于是细看下55干的是什么
def controller_class
params = path_parameters
if params.key?(:controller)
controller_param = params[:controller].underscore
params[:action] ||= 'index'
const_name = "#{controller_param.camelize}Controller"
ActiveSupport::Dependencies.constantize(const_name)
else
PASS_NOT_FOUND
end
end
要想知道加载哪个controller,需要从url中解析。而path_parameters这个方法并没有定义在当前类中,所以,进入该binding,检查path_parameters的source_location。不过,在当前类Request中method被重新定义过,所以需要拿Kernel的method来绑定当前binding来执行
[2] pry(main)> _bsi_[55]
=> #<binding:70142523212960 actiondispatch::request#controller_class="" home="" z="" .rbenv="" versions="" 2.4.0="" lib="" ruby="" gems="" 2.4.0="" gems="" actionpack-5.0.2="" lib="" action_dispatch="" http="" request.rb:81="">
[3] pry(main)> _bsi_[55].eval('method(:path_parameters).source_location')
ArgumentError: wrong number of arguments (given 1, expected 0)
from /home/z/.rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/actionpack-5.0.2/lib/action_dispatch/http/request.rb:177:in `method'
[4] pry(main)> _bsi_[55].eval('method = Kernel.instance_method(:method); method.bind(self).call(:path_parameters).source_location')
=> ["/home/z/.rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/actionpack-5.0.2/lib/action_dispatch/http/parameters.rb", 71]</binding:70142523212960>
源码如下,但PARAMETERS_KEY也没定义在该源码文件中
# Returns a hash with the \parameters used to form the \path of the request.
# Returned hash keys are strings:
#
# {'action' => 'my_action', 'controller' => 'my_controller'}
def path_parameters
get_header(PARAMETERS_KEY) || set_header(PARAMETERS_KEY, {})
end
其实仅凭注释也知道它干啥,那索性执行下这个方法吧,应该没有副作用
[8] pry(main)> cd _bsi_[55]
[9] pry(#):1> path_parameters
=> {:controller=>"store", :action=>"index"}
因为目前访问的就是root,而root在route中被指向到store#index,所以也就这样了
接着再看回ActiveSupport::Dependencies.constantize
[12] pry(#):1> ActiveSupport::Dependencies.method(:constantize).source_location
=> ["/home/z/.rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/activesupport-5.0.2/lib/active_support/dependencies.rb", 613]
简单来说,它就是用Inflector来查找类,然后cache起来
require 'active_support/inflector'
module ActiveSupport
module Dependencies
extend self
class ClassCache
def initialize
@store = Concurrent::Map.new
end
def get(key)
key = key.name if key.respond_to?(:name)
@store[key] ||= Inflector.constantize(key)
end
end
Reference = ClassCache.new
# Get the reference for class named +name+.
# Raises an exception if referenced class does not exist.
def constantize(name)
Reference.get(name)
end
end
end
而在调用栈中,仅出现两次const_missing,它们的参数分别是:StoreController和:ApplicationController
[15] pry(main)> cd _bsi_[50]
[16] pry(Object):1> const_name
=> :StoreController
[17] pry(Object):1> exit
=> Object
[18] pry(main)> cd _bsi_[37]
[19] pry(Object):1> const_name
=> :ApplicationController
那么helper是在哪里加载呢?再检查下require_or_load,直接从最近的查起
[21] pry(main)> cd _bsi_[10]
[22] pry(ActiveSupport::Dependencies):1> file_name
=> "/home/z/test_rails/depot/app/helpers/application_helper"
[23] pry(ActiveSupport::Dependencies):1> exit
=> ActiveSupport::Dependencies
[31] pry(main)> cd _bsi_[11]
[32] pry(ActiveSupport::Dependencies):1> file_name
=> "application_helper"
再往上,modules_for_helpers,其源码如下
def modules_for_helpers(args)
args += all_application_helpers if args.delete(:all)
super(args)
end
# Returns a list of helper names in a given path.
#
# ActionController::Base.all_helpers_from_path 'app/helpers'
# # => ["application", "chart", "rubygems"]
def all_helpers_from_path(path)
helpers = Array(path).flat_map do |_path|
extract = /^#{Regexp.quote(_path.to_s)}\/?(.*)_helper.rb$/
names = Dir["#{_path}/**/*_helper.rb"].map { |file| file.sub(extract, '\1'.freeze) }
names.sort!
end
helpers.uniq!
helpers
end
private
# Extract helper names from files in app/helpers/**/*_helper.rb
def all_application_helpers
all_helpers_from_path(helpers_path)
end
从这里可确定,它接受了值为"application"的参数
[34] pry(main)> cd _bs_[15]
[35] pry(ApplicationController):1> all_application_helpers
=> []
[36] pry(ApplicationController):1> args
=> ["application"]
[37] pry(ApplicationController):1> helpers_path
=> []
再super的话,就转化为文件名了,"#{arg.to_s.underscore}_helper"
def modules_for_helpers(args)
args.flatten.map! do |arg|
case arg
when String, Symbol
file_name = "#{arg.to_s.underscore}_helper"
begin
require_dependency(file_name)
rescue LoadError => e
raise AbstractController::Helpers::MissingHelperError.new(e, file_name)
end
mod_name = file_name.camelize
begin
mod_name.constantize
rescue LoadError
# dependencies.rb gives a similar error message but its wording is
# not as clear because it mentions autoloading. To the user all it
# matters is that a helper module couldn't be loaded, autoloading
# is an internal mechanism that should not leak.
raise NameError, "Couldn't find #{mod_name}, expected it to be defined in helpers/#{file_name}.rb"
end
when Module
arg
else
raise ArgumentError, "helper must be a String, Symbol, or Module"
end
end
end
再往上,18和17是这样的,default_helper_module!会被调用,而所谓默认helper,就是当前controller名字转underscore,因此,helpers/目录中会有需有同名的helper的文件
def default_helper_module!
module_name = name.sub(/Controller$/, ''.freeze)
module_path = module_name.underscore
helper module_path
rescue LoadError => e
raise e unless e.is_missing? "helpers/#{module_path}_helper"
rescue NameError => e
raise e unless e.missing_name? "#{module_name}Helper"
end
# When the argument is a string or symbol, the method will provide the "_helper" suffix, require the file
# and include the module in the template class. The second form illustrates how to include custom helpers
# when working with namespaced controllers, or other cases where the file containing the helper definition is not
# in one of Rails' standard load paths:
# helper :foo # => requires 'foo_helper' and includes FooHelper
# helper 'resources/foo' # => requires 'resources/foo_helper' and includes Resources::FooHelper
def helper(*args, &block)
modules_for_helpers(args).each do |mod|
add_template_helper(mod)
end
_helpers.module_eval(&block) if block_given?
end
而default_helper_module!是在inherited时调用的
def inherited(klass)
helpers = _helpers
klass._helpers = Module.new { include helpers }
klass.class_eval { default_helper_module! } unless klass.anonymous?
super
end
此时的子类是ApplicationController
[41] pry(main)> cd _bs_[19]
[42] pry(ActionController::Base):1> klass
=> ApplicationController
总结起来,加载StoreController时,因需要继承ApplicationController,所以加载它,而ApplicationController的继承链上有AbstractController::Helpers,它会导致在inherited时,根据子类的名称去helpers/下找helper,因此,ApplicationController会找到application_helper.rb,StoreController作为ApplicationController的子类,也会去找store_helper.rb
简单来说,按rails的约定,每个controller可有对应的helper在helpers/中,没有也可以。