My solution intercepts the missing method, generates the method  
signature (including named arguments) and spits it back at the user.   
The user fills in the body and ends with an 'end'.

The method is built as a string and simply eval'd against the  
instance, producing a singleton method.  The method string is also  
stored in an array for later printing.

It uses the class of the given parameters as names for the method  
arguments.  This works up to the point where you have multiple  
arguments of the same type.

example:
irb(main):004:0> o.foobar("hello", 3)
def foobar(string, fixnum)
fixnum.times {puts string}
end
=> nil
irb(main):005:0> o.foobar("hello", 3)
hello
hello
hello
=> 3
irb(main):006:0> o.moobar("goodbye")
def moobar(string)
puts string.upcase
end
=> nil
irb(main):007:0> o.moobar("goodbye")
GOODBYE
=> nil
irb(main):008:0> o.qaprint
def foobar(string, fixnum)
   fixnum.times {puts string}
end

def moobar(string)
   puts string.upcase
end
=> nil
irb(main):009:0>

code:

module QAPrototype

   def method_missing(meth, *args)
     arg_list = args.map {|arg| arg.class.to_s.downcase}.join(", ")
     meth_def = "def #{meth}(#{arg_list})\n"
     puts meth_def
     while (line = gets) != "end\n"
       meth_def += "  " + line
     end
     meth_def += "end\n"

     eval meth_def

     @qamethods ||= []
     @qamethods << meth_def
     nil
   end

   def qaprint
     puts @qamethods.join("\n") if @qamethods
   end
end