简体   繁体   English

列出所有Ruby类和方法

[英]List all Ruby classes and methods

For a while now I've wanted a way to inspect all changes made to a given ruby environment when a particular model is loaded. 一段时间以来,我一直希望有一种方法可以在加载特定模型时检查对给定红宝石环境所做的所有更改。 Furthermore, the ability to compare and contrast the methods and classes available in separate versions of ruby, and different Ruby VMs. 此外,具有比较和对比在不同版本的ruby和不同的Ruby VM中可用的方法和类的能力。

I've created some code which uses meta-programming to generate such a list: 我创建了一些使用元编程生成这样的列表的代码:

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"))

The criteria for the list is that it should list all non-inherited instance and class methods. 该列表的标准是它应列出所有非继承的实例和类方法。 Constants are indicated with :: prefix, Class methods are indicated as MyClass::someMethod and instance methods are indicated as follows: #<MyClass>.someMethod . 常量用::前缀表示,类方法表示为MyClass::someMethod ,实例方法表示为: #<MyClass>.someMethod

The script above works for the most part however, it misses out Object and BasicObject . 上面的脚本大部分都起作用,但是错过了ObjectBasicObject IE in the lists created there are no lines prefixed with #<Object>. IE在创建的列表中没有以#<Object>.为前缀的行#<Object>. or Object:: . Object:: Am I missing something obvious? 我是否缺少明显的东西?

I suggest you create a hash for each Ruby version and then save that hash or its contents to a file whose name indicates the Ruby version (eg, v_2-5-1.json or v_2-5-1.txt ) 我建议您为每个Ruby版本创建一个哈希,然后将该哈希或其内容保存到名称指示Ruby版本的文件中(例如, v_2-5-1.jsonv_2-5-1.txt

While I don't fully understand the question, you may find he method ObjectSpace::each_object helpful here. 虽然我不完全理解这个问题,但是您可以在这里找到ObjectSpace :: each_object方法。 For example, 例如,

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]

As you see Object and BasicObject are two keys (classes) in this hash. 如您所见, ObjectBasicObject是此哈希中的两个键(类)。 Let's look at the value of one of the keys: Dir . 让我们看一下其中一个键的值: 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=>[]}

This is for 这是为了

RUBY_VERSION
  #=> "2.5.1"

Comparing the contents of this hash with the doc for Dir for v2.5.1 we see that the results are correct for the class Dir . 将此哈希的内容与Dir for v2.5.1的文档进行比较,我们发现结果对于Dir类是正确的。

Obtaining constants defined within a class C is problematic. 获取在类C定义的常量是有问题的。 C.constants , which I've used above includes inherited constants. 我上面使用的C.constants包括继承的常量。 Were I to write C.constants - C.superclass.constants (mindful that BasicObject.superclass #=> nil ) that would not report inherited constants the are redefined in C (and redefining an inherited constant does not produce a warning message). 我是在写C.constants - C.superclass.constants (注意BasicObject.superclass #=> nil ),它不会在C重新定义继承的常量(并且重新定义继承的常量不会产生警告消息)。

Instead of just looking at classes you may wish to examine all modules ( ObjectSpace.each_object(Module) ) and add a key :is_class to the hash with value true or false ): 您可能希望检查所有模块( ObjectSpace.each_object(Module) ),然后将一个键值:is_class添加到具有truefalse值的哈希中,而不仅仅是查看类:

There may be other keys you may wish to add to the hash. 您可能希望将其他键添加到哈希中。 :superclass and :included_modules (for classes ) are two that comes to mind; :superclass:included_modules (对于classes)是我想到的两个。 :nesting (for non-class modules) is another. :nesting (对于非类模块)是另一个。 See Module::nesting . 参见Module :: nesting I suspect that these observations just scratch the surface, that a meaningful comparison of two Ruby versions will be highly complex. 我怀疑这些发现只是表面上的,两个Ruby版本的有意义的比较会非常复杂。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM