From: Sam Smoot Date: 2007-06-16T07:30:06+09:00 Subject: Get Parameter names from methods Oft asked for, here you go: > module Kernel > > PARAMETERIZED_CLASSES = {} > > def parameterized_require(libpath) > libpath = libpath + '.rb' unless libpath =~ /\.rb$/ > > load_path = $LOAD_PATH.find do |search_path| > File.exists?(File.join(search_path, libpath)) > end > > if load_path.nil? && !File.exists?(libpath) > raise LoadError.new("Could not find library path: #{libpath}") > end > > file_path = (load_path.nil? ? libpath : File.join(load_path, libpath)) > contents = File.read(file_path) > > contents.scan(/^\s*class\s(\w+)/) do |class_name| > PARAMETERIZED_CLASSES[class_name.first.freeze] = file_path > end > > require(libpath) > > rescue => e > raise LoadError.new(e) > end > > end > > class UnboundMethod > > def binding_class > @class_name || @class_name = begin > to_s =~ /\#\ Object.const_get($1) > end > end > > def name > @name || @name = begin > to_s =~ /\#\ $1.freeze > end > end > > def parameters > @parameters || @parameters = begin > parameter_names = [] > > if file_path = PARAMETERIZED_CLASSES[binding_class.name] > if match = /def\s+#{name}\!?(\s+(.+)|\((.+)\))(\;|$)/.match(File.read(file_path)) > parameters_capture = match.captures[1] || match.captures[2] > parameter_names = parameters_capture.split(/\,\s*/).reject do |parameter_name| > parameter_name.empty? || parameter_name == 'nil' > end.map { |s| s.freeze } > end > end > > parameter_names > end > end > > end There's holes in this. It's not a full Ruby parser. But it should work for 99% of your files. The idea is to extend web MVC frameworks like Merb to allow actions like the following: > class Post > def show(id) > @post = Post.find(id) > end > end I got the idea from a .NET project based _loosely_ on Rails: http://castleproject.org/monorail/index.html The problem is Ruby doesn't provide reflection similar to c#'s ParameterInfo object to make this easy. So here we are. I hope someone else finds this useful.