究竟是rails“root”函数定义在哪里?

时间:2013-02-04 22:35:40

标签: ruby-on-rails ruby scope rails-routing

我在rails应用程序中看到如下内容:

Application.routes.draw do
    root :to => "accounts#index"
end

我被告知here如果“/”是要求的路径,这将定义rails路由到哪里。但是,在哪里,这是在rails代码中定义的'root'函数?我不明白为了让这个技巧发挥作用所涉及的范围问题。

我可以看到正在将一个块传递给draw函数。所以我假设draw函数调用yield来执行传递的块。但是我仍然不确定为什么root函数会神奇地在传递块的范围内。

2 个答案:

答案 0 :(得分:5)

rootActionDispatch::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'