It's a hard problem to solve. In general inferring which methods are valid on any given variable or expression is undecidable. So you have to make an approximation, which is hard and the end results usually still disappointing. Here's a little test case:
def foo(x): return x
a = foo("hello")
b = foo(34)
To infer the methods that you can call on `a` and `b` you have to trace through the `foo` function. You can't just run `foo` because what if the input is unknown or what if `foo` contains a loop or is recursive?
def foo(x, i):
if i == 0: return x
else: return foo(x, i-1)
i = int(read_input())
a = foo("hello",i)
b = foo(34,i)
It gets even worse when you have a huge codebase, monkey patching, eval, and other features like that (which Rails uses in copious amounts).