【发布时间】:2018-07-02 14:18:01
【问题描述】:
一段时间以来,我一直想要一种方法来检查在加载特定模型时对给定 ruby 环境所做的所有更改。此外,能够比较和对比不同版本的 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.methods有效地删除了Object和BasicObject中的剩余方法。 -
顺便说一句,实例方法通常写成
ClassName#method_name,而不是#<ClassName>.method_name -
哦,错了...你是绝对正确的... xD我必须抓住这一点。是的,
ClassName#methodName是我考虑过的一种形式。但是我不能像从 ruby 那样执行它,这让我接受了#<>.someMethod语法......虽然我可能想恢复那个决定。
标签: ruby metaprogramming