How to find the module/class where a method comes from in Rails?

Using Rails, I was originally looking for a way to use the resource path helper methods (e.g. users_path) in models, and this gives me the answer: I can use Rails.application.routes.url_helpers.users_path .

Good, but in general and specifically in Rails, how can one find what module/class a method comes from? Are reading the source code or some official docs the only way to find it? Isn’t it possible to, for example, directly check in the debug console to get Rails.application.routes.url_helpers from users_path ?

Answer

I think what you are looking for is similar to this question How to find where a method is defined at runtime?.

In short, in Ruby 2+, (either of) the following would return an 2-element Array of the filename and line-number:

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

You can then work out the Module or Class name for the method.


[Added in EDIT]

To get the module name, you can use method(:users_path).owner instead: cf., Answer1 and answer2.

However, Rails uses a lot of meta programming and dynamic assignments. The url-helper like users_path in the question is one of them.

Quote of @spickermann’s comment to the question

users_path is defined by meta programming and therefore you will not find a method definition with that method name at all in the code.

Quote of @Stefan’s comment to the question

there might multiple such objects. You have to identify the one “closest” to the current self.

Specifically, url_helpers are defined in actionpack-6.*/lib/action_dispatch/routing/route_set.rb for Rails 6.0 and you see the method generate_url_helpers is responsible to (dynamically) generate it. That is why method(:users_path).owner returns something like #<Module:0x0000000117346e18>, which is not really helpful. Even method(:users_path).source_location simply points to the line of

mod.define_method(name) do |*args|

(or something like that, depending on the Rails version), which indicates that the object is dynamically generated.

In consequence, I doubt if there is any easy way to do-all to derive a Rails object (class/module), say, Rails.application.routes.url_helpers from the given helper function like users_path. But an analysis using a combination of methods like owner and source_location would be of great help to pinpoint it and might, in some cases, give you an answer you are looking for.

I note that, as far as this specific case is concerned, the error message written in actionpack-6*.*/lib/abstract_controller/url_for.rb would be of help – quote:

In order to use #url_for, you must include routing helpers explicitly. For instance, include Rails.application.routes.url_helpers.