之前看到有人提过相应的源代码在哪里,不过我现在忘记了,刚好在看 DTrace 有关的资料,Ruby 2.0.0 也提供了 Provider,于是我想试试通过查方法调用的过程,能不能发现点线索(有不正确的地方,希望大家指出来)。
首先是准备 dtrace 脚本,如下:
#!/usr/sbin/dtrace -Zs
#pragma D option quiet
#pragma D option switchrate=10
self int depth;
ruby*:::method-entry
/pid == $target/
{
self->name = copyinstr(arg1);
printf("%*s-> %s in %s @ %d \n", self->depth * 2, "", self->name, copyinstr(arg2), arg3);
self->depth++;
}
ruby*:::method-return
/pid == $target/
{
this->name = copyinstr(arg1);
self->depth -= self->depth > 0 ? 1 : 0;
printf("%*s<- %s @ %s \n",self->depth * 2, "", self->name, copyinstr(arg2) );
}
有关 ruby 的 Provider,可以参见 DTraceProbes
然后运行脚本:
chmod +x ruby_call_flow.d
sudo ./ruby_call_flow.d > d_result.txt
接着开一个 rails 项目的控制台,执行如下语句:
rails c
app.user_path('aaa')
可以得到如下的结果:
-> user_path in /Users/leslie/.rvm/gems/ruby-2.0.0-p247/gems/actionpack-3.2.15/lib/action_dispatch/routing/route_set.rb @ 215
-> hash_for_user_path in /Users/leslie/.rvm/gems/ruby-2.0.0-p247/gems/actionpack-3.2.15/lib/action_dispatch/routing/route_set.rb @ 180
<- hash_for_user_path @ /Users/leslie/.rvm/gems/ruby-2.0.0-p247/gems/actionpack-3.2.15/lib/action_dispatch/routing/route_set.rb
-> url_for in /Users/leslie/.rvm/gems/ruby-2.0.0-p247/gems/actionpack-3.2.15/lib/action_dispatch/routing/url_for.rb @ 143
-> _routes in /Users/leslie/.rvm/gems/ruby-2.0.0-p247/gems/actionpack-3.2.15/lib/action_dispatch/routing/url_for.rb @ 148
<- _routes @ /Users/leslie/.rvm/gems/ruby-2.0.0-p247/gems/actionpack-3.2.15/lib/action_dispatch/routing/url_for.rb
-> url_options in /Users/leslie/.rvm/gems/ruby-2.0.0-p247/gems/actionpack-3.2.15/lib/action_dispatch/testing/integration.rb @ 189
<- url_options @ /Users/leslie/.rvm/gems/ruby-2.0.0-p247/gems/actionpack-3.2.15/lib/action_dispatch/testing/integration.rb
-> url_for in /Users/leslie/.rvm/gems/ruby-2.0.0-p247/gems/actionpack-3.2.15/lib/action_dispatch/routing/route_set.rb @ 579
-> escape_path in /Users/leslie/.rvm/gems/ruby-2.0.0-p247/gems/journey-1.0.4/lib/journey/router/utils.rb @ 44
<- escape_path @ /Users/leslie/.rvm/gems/ruby-2.0.0-p247/gems/journey-1.0.4/lib/journey/router/utils.rb
-> url_for in /Users/leslie/.rvm/gems/ruby-2.0.0-p247/gems/actionpack-3.2.15/lib/action_dispatch/http/url.rb @ 23
<- url_for @ /Users/leslie/.rvm/gems/ruby-2.0.0-p247/gems/actionpack-3.2.15/lib/action_dispatch/http/url.rb
<- url_for @ /Users/leslie/.rvm/gems/ruby-2.0.0-p247/gems/actionpack-3.2.15/lib/action_dispatch/routing/route_set.rb
<- url_for @ /Users/leslie/.rvm/gems/ruby-2.0.0-p247/gems/actionpack-3.2.15/lib/action_dispatch/routing/url_for.rb
<- user_path @ /Users/leslie/.rvm/gems/ruby-2.0.0-p247/gems/actionpack-3.2.15/lib/action_dispatch/routing/route_set.rb
输出格式有点乱,看图:
看了对应的代码,
def define_url_helper(route, name, kind, options)
selector = url_helper_name(name, kind)
hash_access_method = hash_access_name(name, kind)
binding.pry
@module.module_eval <<-END_EVAL, __FILE__, __LINE__ + 1
remove_possible_method :#{selector}
def #{selector}(*args)
url_for(#{hash_access_method}(*args))
end
END_EVAL
helpers << selector
end
也有定义这些方法的过程。
也不知道找对地方了没有?
大家一般遇到常用的方法,而且想找到对应的源码的时候,都是怎么做的?