我有一个具有以下结构的项目:
Project
├── lib
│ ├── project.rb
│ └── thor_commands
│ ├── cli_starter.rb
│ ├── command1.rb
│ └── command2.rb
└── runme
run么
#!/usr/bin/env ruby
require_relative 'lib/project.rb'
project.rb:
Dir[File.dirname(__FILE__) + '/thor_commands/*.rb'].each { |file| require file }
cli_starter.rb
require_relative command1.rb # Why do I need these
require_relative command2.rb #
module MyThorCLI
class Base < Thor
Command1 ...
end
end
如果我在runme cmd1
运行没有require_relative command1
和require_relative command2
的cli_starter.rb
之类的东西,我会收到一个错误:uninitialized constant MyThorCLI::Base::Command1
。
我试图理解为什么我需要require_relative command1
和require_relative command2
虽然project.rb
已经需要一切。
在我看来,这些模块中的模块和类应该在运行时加载,但它失败了。
cli_starter.rb
在需要时引用Command1
,在加载其他文件之前:没有单独的解决步骤。
额外的require_relative
调用确保首先加载这些文件,因此在cli_starter.rb
加载时它们的常量可用。
各种形式的require
基本上等同于在代码中插入文件的内容(如果尚未要求的话)。
所以(取决于Dir[]
从你的glob中找到文件的顺序),整体失败的执行看起来像:
module MyThorCLI
class Base < Thor
Command1 ...
end
end
class Command1
end
没有单独的解决步骤,当它到达Command1
引用时失败,因为尚未遇到类定义 - 下面是几行。
添加这些要求是解决问题的完美合理方法。可能的tricker方法是更改cli_starter.rb
的内容,因此它不会引用其他常量,直到稍后(通过将这些引用放在后面调用的方法中,而不是直接在类主体内)。这是否可行取决于你的班级团体在做什么。
class Base ..
@@first_command = Command1 # this reference is evaluated when it's encountered
def first_command
@@first_command
end
# -->
class Base ..
def first_command
Command1 # this one is evaluated when the method is called
end