Сегодня у меня возникла странная проблема: получил ошибку "недостающий метод" в модуле, но метод был там, и был необходим файл, в котором был определен модуль. После некоторого поиска я нашел круговую зависимость, где 2 файла требовали друг друга, и теперь я предполагаю, что рубиновый молчание прерывает круговое обращение.
Изменить начало: Пример
Файл 'a.rb':
require './b.rb'
module A
def self.do_something
puts 'doing..'
end
end
Файл 'b.rb':
require './a.rb'
module B
def self.calling
::A.do_something
end
end
B.calling
Выполнение b.rb дает b.rb:5:in 'calling': uninitialized constant A (NameError)
. Необходимо, чтобы они были для обоих файлов, поскольку они предназначены для запуска из командной строки (я пропустил этот код, чтобы он был коротким).
Так что B.calling должен быть там. Одно из возможных решений состоит в том, чтобы обернуть запрос в if __FILE__ == $0
, но это не кажется правильным способом.
Изменить конец
чтобы избежать этих труднодоступных ошибок (не было бы лучше, если бы требование бросило исключение, кстати?), есть ли какие-то рекомендации/правила о том, как структурировать проект и где нужно что? Например, если у меня есть
module MainModule
module SubModule
module SubSubModule
end
end
end
где мне нужно подмодули? все в основном, или только суб в главном и подпункте в суб?
любая помощь будет очень приятной.
Резюме
Объяснение, почему это происходит, обсуждается в forforfs ответе и комментариях.
До сих пор лучшая практика (как указано или намекала на lain), кажется, следующая: (пожалуйста, исправьте меня, если я ошибаюсь):
- помещает каждый модуль или класс в верхнее пространство имен в файл, названный в честь модуля/класса. в моем примере это будет 1 файл с именем 'main_module.rb.' если есть подмодули или подклассы, создайте каталог, названный в честь модуля/класса (в моем примере - каталог "main_module", и поместим файлы для подклассов/подмодулей там (в примере 1 файл с именем "sub_module.rb" ) повторите это для каждого уровня вашего пространства имен.
- требуется шаг за шагом (в примере для
MainModule
потребуетсяSubModule
, а дляSubModule
потребуетсяSubSubModule
) - отделить "код" от кода "define". в исполняемом коде требуется один раз ваш модуль/класс верхнего уровня, поэтому из-за 2. теперь все функции библиотеки должны быть доступны, и вы можете запускать любые определенные методы.
спасибо всем, кто ответил/прокомментировал, это мне очень помогло!