[英]List all Ruby classes and methods
一段时间以来,我一直希望有一种方法可以在加载特定模型时检查对给定红宝石环境所做的所有更改。 此外,具有比较和对比在不同版本的ruby和不同的Ruby VM中可用的方法和类的能力。
我创建了一些使用元编程生成这样的列表的代码:
arr = []
arr << "Ruby version " + ::RUBY_VERSION
arr << ""
Module.constants.each do |const|
if ::Module.const_defined? const
#If for whatever reason const_get fails, then rescue.
begin
obj = Module.const_get(const)
if obj
if obj.is_a? Class
# Class methods
arr << (obj.singleton_methods).sort.map do |method_sym|
obj.to_s + "::" + method_sym.to_s
end
# Instance methods
arr << (obj.instance_methods - (obj.superclass ? obj.superclass.instance_methods : []) - Object.methods).sort.map do |method_sym|
"#<" + obj.to_s + ">." + method_sym.to_s
end
elsif obj.is_a? Module
arr << (obj.methods - Module.methods).sort.map do |method_sym|
obj.to_s + "::" + method_sym.to_s
end
else
# Methods
arr << "::" + const.to_s
end
end
rescue
end
end
end
File.new("D:\\methods_#{::RUBY_VERSION}.txt","w").write(arr.flatten.sort.join("\n"))
该列表的标准是它应列出所有非继承的实例和类方法。 常量用::
前缀表示,类方法表示为MyClass::someMethod
,实例方法表示为: #<MyClass>.someMethod
。
上面的脚本大部分都起作用,但是错过了Object
和BasicObject
。 IE在创建的列表中没有以#<Object>.
为前缀的行#<Object>.
或Object::
。 我是否缺少明显的东西?
我建议您为每个Ruby版本创建一个哈希,然后将该哈希或其内容保存到名称指示Ruby版本的文件中(例如, v_2-5-1.json
或v_2-5-1.txt
)
虽然我不完全理解这个问题,但是您可以在这里找到ObjectSpace :: each_object方法。 例如,
h = ObjectSpace.each_object(Class).with_object({}) do |c,h|
h[c] = { cm: c.methods(false).sort, im: c.instance_methods(false).sort,
con: c.constants.sort }
end
h.keys && [Object, BasicObject]
# [Object, BasicObject]
如您所见, Object
和BasicObject
是此哈希中的两个键(类)。 让我们看一下其中一个键的值: Dir
。
h[Dir]
#=> {:cm=>[:[], :chdir, :children, :chroot, :delete, :each_child, :empty?,
# :entries, :exist?, :exists?, :foreach, :getwd, :glob, :home,
# :mkdir, :open, :pwd, :rmdir, :unlink],
# :im=>[:close, :each, :fileno, :inspect, :path, :pos, :pos=, :read,
# :rewind, :seek, :tell, :to_path],
# :con=>[]}
这是为了
RUBY_VERSION
#=> "2.5.1"
将此哈希的内容与Dir for v2.5.1的文档进行比较,我们发现结果对于Dir
类是正确的。
获取在类C
定义的常量是有问题的。 我上面使用的C.constants
包括继承的常量。 我是在写C.constants - C.superclass.constants
(注意BasicObject.superclass #=> nil
),它不会在C
重新定义继承的常量(并且重新定义继承的常量不会产生警告消息)。
您可能希望检查所有模块( ObjectSpace.each_object(Module)
),然后将一个键值:is_class
添加到具有true
或false
值的哈希中,而不仅仅是查看类:
您可能希望将其他键添加到哈希中。 :superclass
和:included_modules
(对于classes)是我想到的两个。 :nesting
(对于非类模块)是另一个。 参见Module :: nesting 。 我怀疑这些发现只是表面上的,两个Ruby版本的有意义的比较会非常复杂。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.