Debugging is something that (un)fortunately we as developers are all used to doing, but depending on the language, the techniques and tools might differ, if ever so slightly.
Ruby being a language that relies heavily on methods without namespacing (i.e. you call a method the same way regardless of it being defined in the same class, in a parent class, in an included module, a global method), it is at times hard to know where a method you’re using is defined. There are other issues inherent to this behaviour, but that’s a whole other story.
As a stepping stone to helping us with solving this issue, let’s look at the
method method, which creates an instance of
Method with the method you want. I said method way to many times on that sentence, so here’s an example to help consolidate the idea:
str = "I am a String" str_size = str.method(:size) str_size.class # => Method str_size.call # => 13
Hopefully it is now clearer that
method gets us a
Proc like object that we can call later. As an apart, this can be useful (albeit not the most performant solution) when paired with symbol to proc.
def double(num) num * 2 end [1, 2].map(&method(:double)) # => [2, 4]
Without the call to
method this would try to call
double on the instance of
Fixnum . This is way we don’t have to write the full block nor resort to monkey patching.
In some situation we might be able to call methods that could only be called from a block otherwise. Like
[4, 9, 16].map(&Math.method(:sqrt)) # => [2.0, 3.0, 4.0]
Diving into the source
Now that we know about the
Method class, it’s time to find out about a very useful method on it, called
source_location . As the name suggest it tells us the file and line where a certain method is defined (except for native method, for which we get
Since Rails methods are not native, it is a good example of a gem where can use this technique.
p method(:has_many).source_location # => ["/[RETRACTED]/activerecord-4.2.5/lib/active_record/associations.rb", 1258]
Method class has some other useful method to introspect on methods, such as
original_name , check it out.
Hopefully this was useful, and can be helpful when you’re really confused as to where a method is really defined, but as a first pass you can use
ctags to solve the same issue (with the difference that
ctags cannot know for sure which method is actually being called, if it is a common name, or is overridden a lot). There is a RubyBit about
ctags if you’re interested.
More Ruby Bits
If you’ve enjoyed this Ruby Bit you should really subscribe toour newsletter, where other Ruby Bits and more great articles are shared every week.