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.