Ruby has a linters, but this sort of problem is hard to solve with a linter in a dynamically typed language. It's even harder in a Rails environment since Rails adds many methods to your classes at run time.
Yeah, since it's a dynamically typed lang with inheritance and late binding, doesn't performing static analysis on Ruby code to determine whether a method is defined or not, basically require a solution to the halting problem?
I'm under the impression that you have to actually execute Ruby code to find out with certainty where the methods it calls are defined.
You can solve the "90%" problem statically. My Ruby-compiler-in-progress warns of methods that have not been seen, and I may eventually add some (entirely optional) pragma to allow hinting to reduce false positives (though getting that non-intrusive will be a fun challenge).
But you are right, the general case does require a solution to the halting problem, something which is trivial to demonstrate very explicitly:
eval(STDIN.gets)
42.will_i_halt?
Put that in a file, and run it. Press enter, and it halts. Or cut and paste something like this, and it doesn't:
class Fixnum; def will_i_halt?; loop {}; end; end
And consider that even "require" is a practical equivalent to "eval", so trying to look for eval() calls and similar constructs and think you're safe doesn't work, unless you have a guarantee that the interpreter load paths will be the same when the code is run as what you think it'll be.
But in more pragmatic terms, this is a real issue because many Ruby ORMs for example will add methods that depends on the current state of the databases they connect to, so many typical Ruby applications will actually validly use method names that are not explicitly defined anywhere.
Such things are usually solved by parsing the structured javadoc-like API documentation for classes and methods in addition to the code itself. At least that's how it's done in the PHP world and it works quite well. Obviously it's not going to cover 100% of the cases, but much better than nothing.
Plus it incentivizes you to write this documentation in the first place, which you can then instantly bring up inside the IDE from any place where the method is used.
I'm under the impression that you have to actually execute Ruby code to find out with certainty where the methods it calls are defined.