我是从cli上传递的参数动态定义模块名称,例如Required::Module::#{ARGV.first}
有没有办法检查该模块是否存在?另外,如何在其上运行方法而不知道它的确切名称?
答案 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?
。
如果您的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_get
和const_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?