Знайдіть класи, доступні в модулі


75

У мене є модуль MyModule. Я динамічно завантажую в нього класи. Як я можу отримати список класів, визначених у його просторі імен?

Приклад:

def load_plugins
  Dir.glob(File.dirname(__FILE__) + '/plugins/*.rb') do |f|
    MyModule.class_eval File.read(f)
  end

  # now how can I find the new classes I've loaded into MyModule?
end

Слід сказати, що кожен fмістить щось на зразок "клас Foo; кінець".

Ви також можете думати про це так: у Rails, як я міг програмно знаходити всі класи, визначені в модулі ActiveRecord?

Відповіді:


128

Доступ до занять здійснюється через константи. Класи, визначені в модулі, перераховані як константи в цьому модулі. Тож вам просто потрібно вибрати константи, які відносяться до класів.

MyModule.constants.select {|c| MyModule.const_get(c).is_a? Class}

7
Одне: чому ви використовуєте цей тест замість "MyModule.const_get (c) .is_a? Class"? Я не знайомий із таким використанням "===".
joshuaxls

3
Немає вагомих причин. Версія === була для мене просто більш читабельною. Використовуючи is_a? буде працювати так само добре.
Чак

6
Уникайте явного використання оператора рівності випадків ===. Як випливає з назви, воно позначається неявним використанням caseвиразів, і поза ними воно видає досить заплутаний код. [Посібник зі стилів ]
Джеймс Фернандес,

Не знаю чому, але це не працює на вбудованих модулях Ruby, таких як Kernel, Comparable та Enumerable.
вішнупрасант

1
@Vizkrig: AFAIK ці модулі не повинні мати класів. Якщо ви шукаєте класи, які містять модуль, а не класи, які знаходяться в модулі, це вже інше питання .
Чак

1

Якщо ви перебуваєте на рейках, вам потрібно спочатку отримати доступ до констант, щоб вони з’явились, бо вони ліниво завантажені.

MyModule::NotAClass = "not a class"

MyModule.constants => [:NotAClass]

MyModule::AClass => :AClass # Access class for it to be autoloaded

MyModule.constants => [:AClass, :NotAClass]

# Now, select the constants which are class instances

MyModule.constants
        .map(&MyModule.method(:const_get))
        .select { |constant| constant.is_a? Class} 

 => [MyModule::AClass]**
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.