Проверьте, существует ли модуль в ruby - PullRequest
17 голосов
/ 19 августа 2010

Я динамически определяю имя модуля из аргумента, переданного в cli, например, Required::Module::#{ARGV.first}

Есть ли способ проверить, существует ли этот модуль?Кроме того, как мне запустить методы на нем, не зная его точного имени?

Ответы [ 7 ]

34 голосов
/ 24 августа 2010

Используйте const_defined? для этого.

Required::Module.const_defined?(:ModuleName)

возвращает значение true или false.

14 голосов
/ 19 августа 2010
defined?(Required::Module)

дает "constant", если оно существует, и nil, если оно не существует.

Обновление : Извините, неправильно прочитал ваш вопрос.

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

должен дать вам то, что вы ищете.

8 голосов
/ 19 августа 2010

Проверка существования модуля с использованием метода const_get:

begin
    mod = Required::Module::const_get "ModuleName"
    #It exists
rescue NameError
    #Doesn't exist
end
2 голосов
/ 02 июня 2013

Если вы получили ActiveSupport

mod = ("Required::Module::#{ARGV.first}".constantize rescue nil)
2 голосов
/ 24 августа 2012

Вы должны проверить, если:

  • константа, ссылающаяся на модуль, существует,
  • объект, на который ссылается константа, является модулем.

Попробуйте это:

 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)
1 голос
/ 04 декабря 2014

Текущий выбранный ответ неверен. const_get и const_defined ищут любое имя константы, независимо от объекта, вызывающего этот метод. Например, если я хочу проверить MyModule::Rails внутри приложения Rails, использование const_get вернет обычный модуль Rails.

Чтобы проверить константу в определенном пространстве имен, используйте метод constants и проверьте ваш класс:

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

1 голос
/ 29 июня 2014

В случае, когда вы require что-то расширяете, вы не можете основывать свой тест на константе, поскольку расширение может не определять новый. Вместо этого основывайте его на наличии чего-то другого, например, нового метода.

Я использую приведенное ниже, чтобы проверить, требуется ли open_uri_redirections :

if OpenURI.methods.include?(:redirectable_safe?)
  # extension loaded
else
  # extension not loaded
fi
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...