开发者

Check if module exists in ruby

I'm dynamically defin开发者_如何学Pythoning a module name from an argument passed on the cli, for example Required::Module::#{ARGV.first}

Is there any way to check if that module exists? Also, how would I run methods on it not knowing it's exact name?


Use const_defined? for this.

Required::Module.const_defined?(:ModuleName)

returns true or false.


defined?(Required::Module)

gives "constant" if it exists, and nil if it doesn't.

Update: Sorry, didn't read your question properly.

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

should give you what you're after.


Check for module existence using the const_get method:

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


You have to check if:

  • a constant referring to a module exists,
  • an object that the constant holds reference to is a module.

Try that:

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

Then in your code:

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

It will return true if there is a module of the given name within a given namespace base. The difference from the examples given in other answers is that it will return false if the queried name reffers to a class, not to a module.

Include classes in a test

If you want to change that behavior and force the method to also return true for classes (not just modules) change instance_of? to is_a?.

OOP way

You can also code it in a more object-oriented way if your Required::Module module is the only module you're testing for submodules:

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

Then in your code:

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


If you got ActiveSupport

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


In the case where you require something that extends something else, you can't base your test on a constant because the extension may not define a new one. Instead, base it on the presence of something else, like a new method.

I use the below to test if open_uri_redirections has been required:

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


The currently selected answer is not correct. const_get and const_defined look for any constant name, regardless of the object calling that method. For example, if I wanted to check for MyModule::Rails inside a Rails application, using const_get would return the normal Rails module.

To check for a constant within a specific namespace, use the constants method and check for your class:

MyModule.constants.include?("Rails") # => false


Get the class if it exists:

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

Call a method on the class if it does:

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜