Ruby:如何要求并实例化目录中的所有文件?

时间:2012-02-18 01:13:13

标签: ruby

我正在开发一个允许用户自动要求,实例化和注册特定目录中的类的Gem。我只是不确定如何实现这一目标。这就是我到目前为止所提出的......

Dir[Dir.pwd + '/extensions/*.rb'].each do |file|
  require file
  extension_class = # instantiate the class here
  MyApp.extensions << extension_class
end

如何在不知道它叫什么的情况下实例化该类?

2 个答案:

答案 0 :(得分:6)

听起来你正在建立一个编写软件扩展的系统。由于扩展类可能在某种程度上相似,例如共享一些常用方法,因此有一个名为Extension的基类可能是有意义的,所有扩展类都从该基类继承。

实际上,这对所述问题非常有用,因为当用户从您的类继承时,您可以检测它,并将子类添加到列表中。以下是概念代码的一些证明:

class Extension
  class << self
    attr_reader :list
  end
  @list = []

  def self.inherited(klass)
    @list << klass.new
  end
end

# The MyExt class would be in another file, loaded by require.
class MyExt < Extension
end

p Extension.list   # => [#<MyExt:0xb777d884>]

如果您由于某种原因不想使用子类,那么将Extension作为模块并使用included挂钩而不是inherited同样容易。

就个人而言,我只是删除对.new的调用,因为我没有理由立即实例化该类,但这取决于你。我只会存储一个类列表。

答案 1 :(得分:1)

这是一个有趣的想法,让我摸不着头脑。我找不到谷歌搜索的直接解决方案,所以我玩了一下语言。我提出了三个基本想法:

  • 跟踪所有已加载的类,并在进入时获取新类
  • 使用命名方案将文件名与类相关联
  • 在所需的类上使用某种类型的introspector,以便他们可以注册自己以便将来包含

我决定最喜欢第一个选项;它不要求您以特定方式构造文件,或者扩充类以便知道它们将以这种方式被要求。这是一个基本的实现,借用你的初始结构:

classes = ObjectSpace.each_object(Class).to_a
Dir[Dir.pwd + '/extensions/*.rb'].each do |file|
  require file
  changed_classes = ObjectSpace.each_object(Class).to_a
  (changed_classes - classes).each do |extension_class|
    MyApp.extensions << extension_class
  end
  classes = changed_classes
end