检查ruby中是否存在模块

时间:2010-08-19 07:47:28

标签: ruby

我是从cli上传递的参数动态定义模块名称,例如Required::Module::#{ARGV.first}

有没有办法检查该模块是否存在?另外,如何在其上运行方法而不知道它的确切名称?

8 个答案:

答案 0 :(得分:34)

请使用const_defined?

Required::Module.const_defined?(:ModuleName)

返回true或false。

答案 1 :(得分:14)

defined?(Required::Module)

如果存在则"constant",如果不存在,则nil

更新:抱歉,没有正确阅读您的问题。

defined?(eval("Required::Module::"+string))

应该给你你想要的东西。

答案 2 :(得分:8)

使用const_get方法检查模块是否存在:

begin
    mod = Required::Module::const_get "ModuleName"
    #It exists
rescue NameError
    #Doesn't exist
end

答案 3 :(得分:2)

你必须检查:

  • 存在一个引用模块的常量,
  • 常量保持引用的对象是模块。

试试:

 def module_exists?(name, base = self.class)
   base.const_defined?(name) && base.const_get(name).instance_of?(::Module)
 end

然后在你的代码中:

 module_exists?(ARGV.first, Required::Module)

如果给定名称空间库中存在给定名称的模块,它将返回true。与其他答案中给出的示例的不同之处在于,如果查询的名称引用类而不是模块,它将返回false

在测试中包含类

如果您想要更改该行为并强制该方法也为类(而不仅仅是模块)返回true,请将instance_of?更改为is_a?

OOP方式

如果您的Required::Module模块是您为子模块测试的唯一模块,您也可以采用更加面向对象的方式对其进行编码:

 module Required::Module
   def submodule_exists?(name)
     const_defined?(name) && const_get(name).instance_of?(::Module)
   end
 end
 module_function :submodule_exists?

然后在你的代码中:

 Required::Module.submodule_exists?(ARGV.first)

答案 4 :(得分:2)

如果您有ActiveSupport

mod = ("Required::Module::#{ARGV.first}".constantize rescue nil)

答案 5 :(得分:1)

如果您require某些内容扩展了其他内容,则您无法将测试基于常量,因为扩展可能无法定义新的扩展。相反,它基于其他东西的存在,如新方法。

我使用以下内容测试是否需要open_uri_redirections

if OpenURI.methods.include?(:redirectable_safe?)
  # extension loaded
else
  # extension not loaded
fi

答案 6 :(得分:1)

当前选择的答案不正确。无论调用该方法的对象如何,const_getconst_defined都会查找任何常量名称。例如,如果我想在Rails应用程序中检查MyModule::Rails,则使用const_get将返回正常的Rails模块。

要检查特定命名空间中的常量,请使用constants方法并检查您的班级:

  

MyModule.constants.include?(“Rails”)#=>假

答案 7 :(得分:0)

获取类(如果存在):

dynamic_klass = "Required::Module::#{ARGV.first}".classify.safe_constantize

如果调用了类的方法:

dynamic_klass.send("some_method") if dynamic_klass.present?