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?
精彩评论