Я хочу создать базовую девочку, а затем загрузить все подклассы (плагины) и обработать их все через цикл each
. Это рабочий пример:
require 'set'
class Plugin
# Keep the plugin list inside a set so we don't double-load plugins
@plugins = Set.new
def self.plugins
@plugins
end
def self.register_plugins
# Iterate over each symbol in the object space
Object.constants.each do |klass|
# Get the constant from the Kernel using the symbol
const = Kernel.const_get(klass)
# Check if the plugin has a super class and if the type is Plugin
if const.respond_to?(:superclass) and const.superclass == Plugin
@plugins << const
end
end
end
end
class DogPlugin < Plugin
def self.handle_command(cmd)
p "Command received #{cmd}"
end
end
class CatPlugin < Plugin
def self.handle_command(cmd)
p "Command received #{cmd}"
end
end
Plugin.register_plugins
# Test that we can send a message to each plugin
Plugin.plugins.each do |plugin|
plugin.handle_command('test')
end
Этот пример кода работает отлично. Выход:
"Command received test"
"Command received test"
=> #<Set: {DogPlugin, CatPlugin}>
Однако, в моем приложении rails мои пользовательские реализации находятся в модулях. Допустим, у меня есть модуль A
. В этом случае это не работает.
require 'set'
module A
class Plugin
@plugins = Set.new
class << self
attr_reader :plugins
end
def self.register_plugins
# Iterate over each symbol in the object space
Object.constants.each do |klass|
# Get the constant from the Kernel using the symbol
const = Kernel.const_get(klass)
# Check if the plugin has a super class and if the type is Plugin
if const.respond_to?(:superclass) && (const.superclass == A::Plugin)
@plugins << const
end
end
end
end
end
module A
class MyAction < Plugin
def self.handle_command(cmd)
puts "Command received #{cmd}"
end
end
end
A::Plugin.register_plugins
A::Plugin.plugins.each do |plugin|
plugin.handle_command('test')
end
Set
пусто и ничего не выполняется. Почему?
Смотрите живой пример здесь: https://repl.it/repls/EllipticalDamagedCategory
В сети существуют другие типы примеров плагинов, но они должны инициализироваться по одному. Этот пример кода загружает все плагины и выполняет один и тот же метод во всех них. Мне нужен этот функционал с модулями.