如何在 Rails 中找到方法来自的模块/类?

Posted

技术标签:

【中文标题】如何在 Rails 中找到方法来自的模块/类?【英文标题】:How to find the module/class where a method comes from in Rails? 【发布时间】:2022-01-20 23:08:15 【问题描述】:

使用 Rails,我最初是在寻找一种在模型中使用资源路径辅助方法(例如 users_path)的方法,而 this 给了我答案:我可以使用 Rails.application.routes.url_helpers.users_path

很好,但总的来说,特别是在 Rails 中,如何找到一个方法来自哪个模块/类?阅读源代码或一些官方文档是找到它的唯一方法吗?是不是可以例如直接在调试控制台中签入从users_path获取Rails.application.routes.url_helpers

【问题讨论】:

Ruby 中没有“命名空间”之类的东西。你的问题不清楚。 “命名空间”是什么意思? “来自”是什么意思?您是在询问定义该方法的模块吗?还是定义它的脚本位置? 已编辑。现在没有命名空间了。 澄清后,您的问题与***.com/q/69149392/2988、***.com/a/9003022/2988、***.com/a/7247156/2988 和许多其他问题重复。 在我看来,您对定义方法的位置不感兴趣,而是对可以调用该方法的对象感兴趣。在您的示例中,users_path 是由元编程定义的,因此您根本不会在代码中找到具有该方法名称的方法定义。但是可以在控制器和视图的上下文中在Rails.application.routes.url_helpers 上调用该方法。 @spickermann 另外可能有多个这样的对象。您必须确定与当前自我“最接近”的那个。 【参考方案1】:

我认为您正在寻找的内容类似于此问题How to find where a method is defined at runtime?。

简而言之,在 Ruby 2+ 中,以下(其中之一)将返回文件名和行号的 2 元素数组:

method(:users_path).source_location
my_object.method(:my_method).source_location
# => ["/My/Ruby/Code/some-module.rb", 123]

然后您可以计算出该方法的模块或类名称。


[在编辑中添加]

要获取模块名称,您可以改用method(:users_path).owner:参见Answer1 和answer2。

然而,Rails 使用了大量的元编程和动态赋值。问题中的users_path 之类的url-helper 就是其中之一。

引用@spickermann 对该问题的评论

users_path 是由元编程定义的,因此您在代码中根本找不到具有该方法名称的方法定义。

引用@Stefan 对该问题的评论

可能有多个这样的对象。你必须找出与当前自我“最接近”的那个。

具体来说,url_helpers 在 Rails 6.0 的 actionpack-6.*/lib/action_dispatch/routing/route_set.rb 中定义,您会看到 generate_url_helpers 方法负责(动态)生成它。这就是为什么method(:users_path).owner 返回类似#<Module:0x0000000117346e18> 的东西的原因,这并没有真正的帮助。甚至method(:users_path).source_location 也只是指向了

mod.define_method(name) do |*args|

(或类似的东西,取决于 Rails 版本),表示对象是动态生成的。

因此,我怀疑是否有任何简单的方法do-all 从给定的辅助函数(如users_path)派生一个 Rails 对象(类/模块),例如Rails.application.routes.url_helpers .但是使用ownersource_location 等方法的组合进行分析将非常有助于查明它,并且在某些情况下可能会为您提供您正在寻找的答案。

我注意到,就这个具体案例而言,actionpack-6*.*/lib/abstract_controller/url_for.rb 中写的错误消息会有所帮助——引用:

为了使用#url_for,您必须明确包含路由助手。 例如,include Rails.application.routes.url_helpers

【讨论】:

总比没有线索要好,但我还应该真正阅读代码吗? @akai 我已经编辑了我的答案,以便将我的答案版本添加到您的评论中。

以上是关于如何在 Rails 中找到方法来自的模块/类?的主要内容,如果未能解决你的问题,请参考以下文章

如何检查定义的方法?来自在类中使用的模块,其中包含模块后定义的方法

如何在 Rails 中正确使用控制器辅助模块,以及如何连接这些辅助模块?

如何覆盖模块中的类常量和方法?

如何在Rails中正确使用控制器助手模块,以及如何在这些助手之间建立连接?

在 Rails 中,如何向 String 类添加新方法?

ruby/rails:如何确定是不是包含模块?