我在rails应用程序中看到如下内容:
Application.routes.draw do
root :to => "accounts#index"
end
我被告知here如果“/”是要求的路径,这将定义rails路由到哪里。但是,在哪里,这是在rails代码中定义的'root'函数?我不明白为了让这个技巧发挥作用所涉及的范围问题。
我可以看到正在将一个块传递给draw
函数。所以我假设draw
函数调用yield
来执行传递的块。但是我仍然不确定为什么root
函数会神奇地在传递块的范围内。
答案 0 :(得分:5)
root
在ActionDispatch::Routing::Mapper::Base
上定义,ActionDispatch::Routing::Mapper
包含该内容。
幕后发生的事情比第一眼还要多。
如果我们查看draw
的定义,我们可以看到原因:
# action_dispatch/routing/route_set.rb
def draw(&block)
# ...
eval_block(block)
# ...
end
该块转换为proc(带&
)并传递给eval_block
,后者定义得更远:
def eval_block(block)
# ...
mapper = Mapper.new(self)
# ...
mapper.instance_exec(&block)
end
因此,事实证明,yield
根本没有使用过。我们传递给Application.routes.draw
的块只是在ActionDispatch::Routing::Mapper
的实例的上下文中进行评估。
如果我们向puts self
添加config/routes.rb
,我们可以看到这一点:
Application.routes.draw do
puts self
end
当我们运行rake routes
时,我们会得到类似于以下内容的内容:
#<ActionDispatch::Routing::Mapper:0x007feadf52cbd8>
# ...
如需进一步阅读,请参阅:
http://ruby-doc.org/core-1.8.7/Object.html#method-i-instance_exec https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/routing/route_set.rb#LC296 https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/routing/mapper.rb#LC336 http://www.amazon.com/Metaprogramming-Ruby-Program-Like-Pros/dp/1934356476
答案 1 :(得分:1)
https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/routing/mapper.rb
def root(options = {})
options = { :to => options } if options.is_a?(String)
match '/', { :as => :root, :via => :get }.merge!(options)
end
https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/routing.rb
module Routing
autoload :Mapper, 'action_dispatch/routing/mapper'