我有一个具有以下结构的项目:
Project
├── lib
│ ├── project.rb
│ └── thor_commands
│ ├── cli_starter.rb
│ ├── command1.rb
│ └── command2.rb
└── runme
邵仁枚
#!/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
已经需要了所有内容。
在我看来,这些模块中的模块和类应该在运行时加载,但它失败了。
答案 0 :(得分:1)
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