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

时间:2018-05-23 06:30:57

标签: ruby

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

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 command2cli_starter.rb的内容,则会收到错误:uninitialized constant MyThorCLI::Base::Command1

我正在尝试理解为什么我需要require_relative command1require_relative command2,尽管project.rb已经需要了所有内容。

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

1 个答案:

答案 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