Locate method definition file in Ruby
2021-06-02 2 min
Suppose you want to overwrite (monkey patch) an existing method in a gem.
Testing if the method has been properly overwritten is relatively easy. Just open the Ruby (or Ralis) console and execute it. You’ll see the expected result.
But when the method is private, there’s no easy way to test in console. The method is restricted to the internal use of the class.
In order to check if the method have been correctly overwritten in the console, you can use the method source_location
.
source_location
reveals the source filename holding the method definition.
Class methods
module GemModule
class GemClass
class << self
private
def gem_class_method
puts 'my_class_method'
end
end
end
end
The previous code is overwritting a class method. Open the irb console, and type as follows.
> require 'gem'
=> false
> require './patched_class'
=> false
> GemModule::GemClass.method(:gem_class_method).source_location
=> 'path/to/patched_class.rb'
Instance methods
The same approach can be used for instance methods.
module GemModule
class GemClass
private
def gem_instance_method
puts 'my_instance_method'
end
end
end
And in console.
> require 'gem'
=> false
> require './patched_class'
=> false
> GemModule::GemClass.new.method(:gem_instance_method).source_location
=> 'path/to/patched_class.rb'
Notice the class must be instantiated before accessing the method.
Constants
Following the same example, let’s overwrite a constant.
module GemModule
GEM_CONSTANT = 'MY_CONSTANT'
end
Use const_source_location
to check where a constant has been defined.
> require 'gem'
=> false
> require './patched_class'
=> false
> GemModule.const_source_location('GEM_CONSTANT')
=> 'path/to/patched_module.rb'
Conclusion
This approach to know where exactly methods or contants are defined is not intended only for monkey patching gems.
You can also use it for Rails projects where a module or class may be “opened” in multiple files.