【问题标题】:How to automatically call classes in Ruby script from a specific directory如何从特定目录自动调用 Ruby 脚本中的类
【发布时间】:2017-03-23 21:07:05
【问题描述】:

我有一个目录 /lib 用于存储 *.rb 文件。它们中的每一个都包含一个具有单个类方法remove_user() 的类。

如何使主脚本自动检查这些文件并在所有文件上调用相同的方法?我想将来只在该目录中插入文件,而不以任何方式修改主脚本。

我确实知道如何require 基于“Best way to require all files from a directory in ruby?”的目录中的所有文件,但我不太确定如何从这里“循环”调用这些类。

更新

我尝试了“How do I create automatically a instance of every class in a directory?”中建议的代码

files = Dir.glob("lib/*.rb")

def load_modules(class_files)
  puts class_files
  before = ObjectSpace.each_object(Class).to_a
  class_files.each {|file| require_relative file }
  after = ObjectSpace.each_object(Class).to_a
  (after - before).each {|klass| klass.new.delete_user('myemail@mail.com', 'Audit', 'Test')}

  load_modules(files)
end

它会产生错误:

/Users/apinchuk/RubymineProjects/autoaudit/init.rb:16:in `new': can't create instance of singleton class (TypeError)
from /Users/RubymineProjects/autoaudit/init.rb:16:in `block in load_modules'
from /Users/RubymineProjects/autoaudit/init.rb:16:in `each'
from /Users/RubymineProjects/autoaudit/init.rb:16:in `load_modules'
from /Users/RubymineProjects/autoaudit/init.rb:20:in `<top (required)>'
from -e:1:in `load'
from -e:1:in `<main>'

我找不到关于这个错误的任何信息。

create_uat_robot.rb 的结构如下:

class CreateUatRobot
  def self.delete_user(email, first_name, last_name)
    ...
  end
end

文件名是create_uat_robot.rb

尝试@moveson 建议如下:

files = Dir.glob("lib/*.rb")
files.each {|file| require_relative file }

klasses = Dir["lib/*.rb"].map {|file| File.basename(file, '.rb').camelize.constantize}
klasses.each { |klass| klass.delete_user(arguments) }

为我工作。

【问题讨论】:

  • 请阅读“How to Ask”,包括链接页面“minimal reproducible example”和“How much research effort is expected of Stack Overflow users?”。我们希望看到你努力的证据。你尝试了什么?您是否搜索并没有找到任何东西?你有没有找到东西,但它没有帮助?你试过写代码吗?如果不是,为什么?如果是这样,显示您尝试了什么以及为什么它不起作用的最小代码示例是什么?没有它,您似乎没有尝试并希望我们为您编写它。

标签: ruby


【解决方案1】:

首先你需要创建一个类名数组:

>> klasses = Dir["lib/*.rb"].map {|file| File.basename(file, '.rb').camelize.constantize }

然后你可以依次在它们上调用你的方法:

>> klasses.each { |klass| klass.remove_user }

如果您不使用 Rails,则可以要求 ActiveSupport 的字符串扩展方法 (require 'active_support/core_ext/string'),它将为您提供 camelizeconstantize 方法。

【讨论】:

  • file.split('/').last.split('.').first 似乎是一种非常复杂的方法来处理File.basename(file, ".rb")
  • File.basename 在这里不起作用,因为Dir["lib/*.rb"] 返回一个字符串数组,而不是 File 对象。如果您知道如何返回 File 对象数组,我将编辑答案以反映这一点。
  • File.basename 是一个类方法,而不是一个实例方法,它的第一个参数是一个字符串:File.basename("/foo/bar/baz/my_module.rb", ".rb") # =&gt; "my_module"。看一看:repl.it/Gb4V
  • 啊。是的,现在我明白了。我已经更新了答案。谢谢。
猜你喜欢
  • 1970-01-01
  • 2016-01-07
  • 1970-01-01
  • 2012-06-09
  • 2020-07-12
  • 2021-09-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多