如果我需要一个包含类定义的Ruby文件,如何在不必查看文件内容的情况下发现需要添加哪些类?
例如,如果我有'foobar.rb'文件,只包含以下内容:
class Foo
end
class Bar
end
我知道如果我需要这个文件,我现在可以使用Foo和Bar:
>> require 'foobar' #=> true
>> Foo #=> Foo
>> Bar #=> Bar
假设我不知道foobar.rb的内容是什么,我只是需要它。我怎么会发现Foo和Bar现在是新的类常量?
答案 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
这将只返回新定义的类而不是所有已定义的常量。