Ruby需要多个文件,而不知道它们的类名

Ruby需要多个文件,而不知道它们的类名,ruby,class,methods,Ruby,Class,Methods,假设我有一个需要不同文件的应用程序。每个文件都包含一个单一用途的“东西”。我称之为“东西”,因为我不确定它是一个类还是一个模块 第一件事 # things/one.rb class One def self.do_it "I'm the one" end end 第二个呢 # things/two.rb class Two def self.do_it "I'm not the only one!" end end 现在我需要things目录中

假设我有一个需要不同文件的应用程序。每个文件都包含一个单一用途的“东西”。我称之为“东西”,因为我不确定它是一个类还是一个模块

第一件事

# things/one.rb
class One
  def self.do_it    
    "I'm the one"
  end
end
第二个呢

# things/two.rb
class Two
  def self.do_it    
    "I'm not the only one!"
  end
end
现在我需要
things
目录中的所有文件,并执行
do_it
方法。但我想动态地做这件事——对things文件夹中的每件事,甚至不知道它们的类名

# app.rb
Dir["things/*.rb"].each {|file| require file }

请记住:我只想在things文件中执行代码-它们不一定是类或模块

由于许多原因,您无法可靠地执行此操作,但最重要的是,您没有义务在任何给定文件中声明单个类,或者根本不声明一个类。加载特定目录中的所有文件的想法是正确的,但是如果需要对这些文件进行操作,有两种方法可以解决这个问题

最简单的方法是将这些类声明为某些已知父类的子类。ActiveSupport具有反映特定类的方法,该类是Rails的一部分,但您也可以这样做

第二种最简单的方法是将名称与其中的类关联起来,然后通过算法将文件名转换为类名。这就是Rails自动加载器的工作原理
cat.rb
包含
cat
bad\u dog.rb
包含
BadDog
等等

如果您更仔细地观察像Test::Unit这样的东西是如何工作的,那么在Ruby进程终止之前,任何声明的测试子类都会被执行。这是一个相当简单的系统,它不限制文件的调用,也不限制类的声明位置和方式

Rails倾向于第二种方法,路径在其中传达意图。这使得查找文件更容易预测,但需要开发人员遵守更多的规则才能符合该标准


他们都有优点。选择适用于您的用例的代码。

“我只想执行things文件中的代码-它们不一定是类或模块”–这正是
所要求的:它执行文件中的代码。注意:您需要
所要求的是相对的
,而不是指“things”,您的意思是每个文件都包含一个可能是类的模块。“想要”不是一个词,很有趣!一种方法是:
classes\u before=ObjectSpace.each\u object(Class).to\u a;Dir[“things/*.rb”]。每个{文件|需要|相对文件};类_after=ObjectSpace.each_Uobject(Class)。to_uA;do|it_classes=(classes_after-classes_before)。选择{klass | klass.respond_to?(:do_it)}
请注意这种方法,因为您希望这些文件立即实例化任何类,而如果您处理的是
自动加载
声明或其他形式的延迟加载,则可能不是这种情况,再加上动态规划,工厂可能会按需生成类。真的。不过OP没有提到自动加载,而是说每个文件都有一件事。不过,我意识到我的代码没有考虑模块。@EricDuminil我只是在这里添加一些警告,因为在Ruby方面,程序员有很多自由。没有我所描述的内部规则和标准,很难准确地知道该做什么。你的代码是一个很好的例子,说明了如何在所有东西都正确加载的情况下进行挖掘。明白了。谢谢你的解释!