[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Get Parameter names from methods

Sam Smoot

6/15/2007 10:30:00 PM

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 =~ /\#\<UnboundMethod\:\s(\w+)/
> Object.const_get($1)
> end
> end
>
> def name
> @name || @name = begin
> to_s =~ /\#\<UnboundMethod\:\s\w+\#(\w+)/
> $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/...

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.

1 Answer

Sam Smoot

6/16/2007 2:57:00 AM

0

Uhmm, yeah. Nevermind that version. Perfection!:

> require 'parse_tree'
>
> class UnboundMethod
>
> def binding_class
> @class_name || @class_name = begin
> to_s =~ /\#\<UnboundMethod\:\s(\w+)/
> Object.const_get($1)
> end
> end
>
> def name
> @name || @name = begin
> to_s =~ /\#\<UnboundMethod\:\s\w+\#(\w+)/
> $1.freeze
> end
> end
>
> def parameters
> @parameters || @parameters = begin
> ParseTree.new.parse_tree_for_method(binding_class, name)[2][1][1][1..-1]
> end
> end
>
> end

Now any UnboundMethod (written in Ruby) can be inspected for it's
parameters, without any fancy require hacks...