Я работаю с проектом Rails и не совсем понимаю, как работает автозагрузка Rails в моем конкретном случае. Я прочитал несколько статей об автозагрузке Rails и ее подводных камнях, но они мне не очень помогли
Я строю процессор для задач (упражнений). Каждая задача имеет свой собственный класс процессора в Tasks::<TaskName>::Processor
, который смешивается в модуле Tasks::Processor
, который содержит общий код для процессоров задач. Процессоры содержат класс Get
(для обработки запросов GET), расположенный в Tasks::<TaskName>::Processor::Get
, который смешивается с Tasks::Processor::Get
, содержащим общий код Get
.
Я немного упростил код, чтобы было проще понять и убрал всю бизнес-логику, но этого все же достаточно, чтобы воспроизвести проблему.
Итак, проблема в следующем:
когда я запускаю Tasks::TaskOne::Processor.new.get
, он работает нормально, но если я запускаю Tasks::TaskTwo::Processor.new.get
, после этого выдается ошибка: NoMethodError: неопределенный метод `new 'для Tasks :: Processor :: Get: Module, Это также работает наоборот: если я сначала запускаю код процессора TaskTwo, то он работает нормально, но процессор TaskOne выдаст ошибку. Он просто не может найти конкретную реализацию Get и вместо этого находит универсальный модуль и пытается создать его экземпляр, что, очевидно, невозможно.
Вот код вместе со структурой.
Общий код:
приложение / модели / задачи / processor.rb
module Tasks
# generic Processor (mixed in by custom processors)
module Processor
# ...
end
end
приложение / модели / задачи / процессор / get.rb
module Tasks
module Processor
# generic Get
module Get
# ...
end
end
end
Код TaskOne:
приложение / модели / задачи / task_one / processor.rb
module Tasks
module TaskOne
# processor for task_one
class Processor
include Tasks::Processor # mix in generic task processor
def get
Get.new.call
end
end
end
end
приложение / модели / задачи / task_one / процессор / get.rb
module Tasks
module TaskOne
class Processor
# task_one's processor's custom Get
class Get
include Tasks::Processor::Get # mix in generic Get
def call
puts "in task_one's Processor's Get"
end
end
end
end
end
И практически идентичный код для TaskTwo:
приложение / модели / задачи / task_two / processor.rb
module Tasks
module TaskTwo
# processor for task_two
class Processor
include Tasks::Processor # mix in generic task processor
def get
Get.new.call
end
end
end
end
приложение / модели / задачи / task_two / процессор / get.rb
module Tasks
module TaskTwo
class Processor
# task_two's processor's custom Get
class Get
include Tasks::Processor::Get # mix in generic Get
def call
puts "in task_two's Processor's Get"
end
end
end
end
end
Скорее всего, это как-то связано с автозагрузкой Rails, потому что когда я использую обычный ruby и вручную требую все файлы и пытаюсь запустить код, проблема не возникает.
Не могли бы вы объяснить, почему это так, и скажите мне, как лучше всего избежать этой проблемы? Похоже, Rails не нравится тот факт, что у меня есть класс и модуль с одинаковыми именами, и это путает, но я подумал, что это не должно быть проблемой, поскольку они находятся в разных пространствах имен.
Я мог бы просто назвать универсальный класс как-то по-другому, но мне бы очень хотелось понять, почему использование одного и того же имени класса как для конкретной реализации, так и для универсального, работает только для первой загрузки, а не для следующей. Большое спасибо за вашу помощь!
P.S. моя версия Ruby 2.5.1, а версия Rails 5.2.1