You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

给定Ruby文件my.rb,能否动态获取其中定义的模块名?

如何动态获取Ruby文件中定义的模块名?

当然可行!我给你分享几种实用的方法,根据你的场景需求选择就好:

方法一:对比加载前后的模块集合(适合已加载文件的场景)

这种思路是先记录加载文件前已存在的顶级模块,加载后对比找出新增的模块,非常适合你已经通过require/require_relative加载文件的情况:

# 记录加载前所有顶级模块(排除嵌套模块)
existing_top_modules = ObjectSpace.each_object(Module)
  .select { |mod| mod.name&.split('::').size == 1 }
  .to_set

# 动态加载目标文件
require_relative 'my.rb'

# 找出加载后新增的顶级模块
new_modules = ObjectSpace.each_object(Module)
  .select { |mod| mod.name&.split('::').size == 1 }
  .to_set - existing_top_modules

# 输出结果
puts "动态加载的模块名:#{new_modules.map(&:name).join(', ')}"

如果你的文件里有嵌套模块(比如module MyModule::SubModule),只需要调整筛选条件,把split('::').size == 1改成你需要的层级即可。

方法二:解析文件语法树(无需加载文件,无副作用)

如果你不想实际加载文件(避免文件中的执行代码带来副作用),可以通过解析Ruby的语法树来提取模块定义。这种方法需要用到parser gem,先安装:gem install parser,然后用下面的代码:

require 'parser/current'

# 读取目标文件内容
file_content = File.read('my.rb')

# 解析生成抽象语法树(AST)
ast = Parser::CurrentRuby.parse(file_content)

# 遍历AST提取所有模块名
module_names = []
ast.children.each do |node|
  next unless node.type == :module

  # 处理嵌套模块的情况,拼接完整模块名
  full_name = node.children.first.children.map { |n| n.children.first }.join('::')
  module_names << full_name
end

puts "文件中定义的模块名:#{module_names.join(', ')}"

这个方法的优势是完全不会执行文件里的代码,安全可控,还能一次性提取所有模块(包括嵌套的)。

额外提示

  • 如果你的my.rb里只定义了一个模块,且确定是顶级模块,也可以尝试直接遍历ObjectSpace找最近加载的模块,但前两种方法更通用可靠。
  • 注意如果模块名是动态生成的(比如用字符串拼接定义模块),语法树解析的方法可能无法准确识别,这种情况只能用第一种加载后对比的方法。

内容的提问来源于stack exchange,提问作者TieDad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 12:13:28