如何在需要Ruby文件时发现加载了哪些类

时间:2014-03-31 17:33:03

标签: ruby

如果我需要一个包含类定义的Ruby文件,如何在不必查看文件内容的情况下发现需要添加哪些类?

例如,如果我有'foobar.rb'文件,只包含以下内容:

class Foo
end

class Bar
end

我知道如果我需要这个文件,我现在可以使用Foo和Bar:

>> require 'foobar' #=> true
>> Foo #=> Foo
>> Bar #=> Bar

假设我不知道foobar.rb的内容是什么,我只是需要它。我怎么会发现Foo和Bar现在是新的类常量?

4 个答案:

答案 0 :(得分:2)

您可以使用 hacky 方法执行此操作。每次使用class关键字或Class::new定义新的自定义类时,无论如何都会使用挂钩方法Class#inherited方法。

因此,请将以下代码放入您的文件中:

class Object
  def self.inherited(subclass)
   (@classes ||= []) << subclass
  end
  def self.display_all_loaded_custom_class
    @classes
  end
end

class Foo;end
class Bar;end

self.class.display_all_loaded_custom_class # => [Foo, Bar]

无论何时定义任何类,而不将其作为任何其他类的子类,Object将成为这些类的默认超类。因此,非常期望您需要定义Object::inherited方法来跟踪这些方法。

答案 1 :(得分:2)

使用系统跟踪器:

# one.rb
class Foo
end

class Bar
end

# two.rb
require 'tracer'

Tracer.add_filter {|event| event == 'class' }

Tracer.on {
  require './one'
}

>> #0:/Users/sergio/projects/tmp/mp/one.rb:1::C: class Foo
>> #0:/Users/sergio/projects/tmp/mp/one.rb:4::C: class Bar

文档:Tracer

答案 2 :(得分:1)

如果您只对顶层定义的类和模块感兴趣,即不在模块内部,则可以这样做:

previously_defined = Object.constants
require 'foobar'
just_defined = Object.constants - previously_defined

(如果你不想要,你必须过滤出模块的名称。)

如果你需要所有课程,你可以这样做:

previously_defined = []
ObjectSpace.each_object(Class) { |cls| previously_defined << cls }
require 'foobar'
just_defined = []
ObjectSpace.each_object(Class) { |cls| just_defined << cls }
just_defined -= previously_defined

答案 3 :(得分:0)

您可以尝试:

classes = ObjectSpace.each_object(Class).to_a
require 'foobar'
new_classes = ObjectSpace.each_object(Class).to_a - classes

这将只返回新定义的类而不是所有已定义的常量。