views:

102

answers:

3

I have a ruby method (deactivate!) that is on an activeRecord class. However, I can't seem to find where that method is declared.

There have been numerous developers on this project, so it could be anywhere. There is a deactivate! on an unrelated class, but it doesn't seem to get called.

Any ideas how to find all the superclasses for an instace, or where to find the code for deactivate!?

A: 

As a first stab, try the Jump to Declaration feature of your IDE. Depending on how good your IDE's static type inference is, it should take you right there.

If that doesn't work, set a breakpoint on that call, fire up the debugger and step into the method.

Jörg W Mittag
-1. Question is about Ruby. Static type inference doesn't exist. Plus there's a 99% chance he's not using an IDE.
fig
@fig-gnuton: Diamondback Ruby, Eclipse Ruby Development Tools, Aptana RadRails, CodeGear 3rdRail, SapphireSteel Ruby in Steel for Visual Studio and the NetBeans Ruby Plugin have *all* been doing static type inference for Ruby for *years*. And unless he's using Notepad, he probably uses either an IDE or a programmable text editor like TextMate, Vim or Emacs which can be *turned* into an IDE. Also, a debugger is part of the standard library, it doesn't require an IDE or even a third-party library (although the `ruby-debug` library is much better, but that still doesn't require an IDE).
Jörg W Mittag
Jorg - well played. But chances are he wouldn't be using anything that had static type inference. And debugging doesn't seem like the best approach compared with mckeed's.
fig
@fig-gnuton: Walking the ancestors chain tells you the class or module that the method is attached to, but not where it is defined. The debugger tells you where it is defined, but not how it ended up in the ancestors chain. Those two pieces of information are complementary.
Jörg W Mittag
+9  A: 

When I need to find where a method is declared on some class, say 'Model', I do

Model.ancestors.find {|c| c.instance_methods(false).include?('deactivate!') }

This searches the ancestor tree in the same order that ruby does for the first that has the method in instance_methods(false), which only includes non-inherited methods.

Note: in ruby 1.9, the methods are listed as symbols, so do

Model.ancestors.find {|c| c.instance_methods(false).include? :deactivate! }
mckeed
Ha! Ancestors is a Class method, not an instance method. No wonder I couldn't find it.Thx,Joe
Joe Fair
Another wonderful, succinct answer, @mckeed. Thanks :)
macek
+1  A: 

First question would be: is it an actual method? Does obj.method(:deactivate!) raise an error?

If it doesn't, then you can use Method#source_location(in Ruby 1.9 only, and backports can't support it):

obj.method(:deactivate!).source_location

If it does raise a NoMethodError, it is handled via method_missing. This makes it hard to track. If it accepts arguments, I'd try sending the wrong type and using the backtrace of the raised exception.

Are you using state_machine? If you have an event transition called :deactivate, the model will have the method #deactivate! created automatically.

Marc-André Lafortune