Задача: у меня есть некоторое количество «задач», которые можно выполнять параллельно. Описание задачи являет собой модуль с методами и константами. Есть клас-враппер, который собственно и запускает задачи.
Проблемма: я не нашел (хорошего) способа как «inject`ить» все внутренности модуля в свой отдельно взятый инстанс враппера.
Я перепробывал
- class_eval(«include ..»)
- instance_eval(«include ..»)
- Object.extend()
Но ни один не помог. Наиболее близко ктому что мне надо был extend. Но он к сожалению не «копировал» константы. А документация по этому поводу разходится
extend(module, ...) → obj click to toggle source Adds to obj the instance methods from each module given as a parameter.
extend_object(obj) → obj click to toggle source Extends the specified object by adding this module’s constants and methods (which are added as singleton methods). This is the callback method used by Object#extend.
Сейчас я вижу 2 возможных костыляworkaround`а:
- возвращать каждую константу в отдельном методе
- в инстансе работать на прямую с методами/константами
Код прототипа (я надеюсь гуру понимают почему он работает правильно)
#!/usr/bin/env ruby
# encoding: UTF-8
require 'thread'
require_relative 'module_a'
require_relative 'module_b'
class TaskRunner
def initialize(_module)
print "#{self.__id__}:#{_module.name.to_s}\n"
self.class.class_eval("include #{_module}")
process_test_method
end
def process_test_method
print "#{self.__id__}:#{test_method}\n"
end
end
scheduled_tasks = []
Module.constants.select { |module_name|
module_name.to_s.start_with?('Module_')
}.each { |name|
scheduled_tasks << Thread.new do
TaskRunner.new(Kernel.const_get(name))
end
}
scheduled_tasks.each { |task| task.join }
модуль №1
#!/usr/bin/env ruby
# encoding: UTF-8
#
module Module_a
PROVIDES = 'architectures'
def test_method
'I am from Module_a::method'
end
end
модуль №1
#!/usr/bin/env ruby
# encoding: UTF-8
#
module Module_b
PROVIDES = 'platforms'
def test_method
'I am from Module_b::method'
end
end