在一个项目/宝石中需要多个模块

问题描述 投票:0回答:1

我有一个具有以下结构的项目:

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 command1require_relative command2cli_starter.rb之类的东西,我会收到一个错误:uninitialized constant MyThorCLI::Base::Command1

我试图理解为什么我需要require_relative command1require_relative command2虽然project.rb已经需要一切。

在我看来,这些模块中的模块和类应该在运行时加载,但它失败了。

ruby
1个回答
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
© www.soinside.com 2019 - 2024. All rights reserved.