読者です 読者をやめる 読者になる 読者になる

インスタンスと結果を渡してそれに合うメソッドを探してくれるメソッドMethodFinder

Stick it in Your ~/.irbrc: MethodFinder - RedHanded

http://redhanded.hobix.com/inspect/stickItInYourIrbrcMethodfinder.html

のリンク先にあるMethodFinderがすごい。


Andrew Birkett's MethodFinder in Ruby
http://www.nobugs.org/developer/ruby/method_finder.html

ここに書いてあるようにすると、インスタンスとその結果を書くだけでそういうことをするメソッドを探してきてくれるようです。

.irbrcに書いておけば、Refeなどとは違った観点で調べ物をするときに役立ちそうです。

追記

MethodFinderはインスタンスを片っ端からメソッドを試していって例外が発生したらそれを捨てているようで、互換性などの観点から警告を出すようになっているメソッド(id, typeなど)を毎回呼び出してしまうので警告を出さないようにした。

MethodFinder#findを呼び出す直前で$VERBOSEをnilにし、呼び出した後に$VERBOSEをまた元に戻せばいい感じです。

さらに追記(06/05/30)

Stick it in Your ~/.irbrc: MethodFinderの方は使い方に間違いがあります。

"hello".what? == 5 # こんな感じ
"hello".length     # 出力は少し変更してます 
"hello".size
 # => [length, size]

という風に == が抜けていますね。id:ghidenさん情報ありがとうございます。
http://d.hatena.ne.jp/ghiden/20060530/1148968735

コピペしたい人もいるかもしれないので一応ソースも貼り付けておきます。

class Object
  def mega_clone
    self.clone
  rescue
    self
  end

  def what?(*a)
    MethodFinder.new self, *a
  end
end

class MethodFinder  
  def self.find(obj, expected, *args)
    tmp = obj.methods.select {|name| obj.method(name).arity == args.size }
    # p tmp         
                    
    flag = $VERBOSE 
    $VERBOSE = nil  
    tmp = tmp.select {|name|
      begin         
        obj.mega_clone.method(name).call(*args) == expected
      rescue        
      end           
    }               
                    
    $VERBOSE = flag 
                    
    tmp             
  end               
                    
  def self.show(obj, expected, *args)
    find(obj, expected, *args).each do |name|
      print "#{obj.inspect}.#{name}"
      print "(" + args.map {|o| o.inspect }.join(", ") + ")" unless args.empty?
      puts          
    end             
  end               
                    
  def initialize(obj, *args)
    @obj = obj      
    @args = args    
  end               
                    
  def ==(val)       
    MethodFinder.show @obj, val, *@args
  end               
end 

それにしてもmega_cloneというメソッド名は気に入らない…。