Require的范围

The scope of Require

我在访问我在另一个文件中声明的模块时遇到问题,我想知道我在概念上是否有这个权利。让我解释一下。

如果我像这样设置文件 a、b 和 c

档案一

module HelloWorld
  def greet
    "hello world"
  end
end

文件 b

require "a"

文件 c

require "b"
include HelloWorld

puts greet

所以是 a -> b -> c,这行得通吗?

现在如果我这样做会怎样

档案一

module HelloWorld
  def greet
    "hello world"
  end
end

文件 b

include HelloWorld

puts greet

文件 c

require "a"
require "b"

这会改变什么吗?在我看来,gems - 一旦需要 - 无论什么文件都可以访问,但在第二种情况下我无法访问模块。感谢任何帮助。

更新:我测试了这两种情况,它们都有效,这让我相信这不是概念问题,而是我的代码中的错误。我将开始调试项目。

当我尝试 运行 您的代码时,我收到以下错误消息

$ ruby c.rb
~/.rbenv/versions/2.3.1/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require': cannot load such file -- a (LoadError)
  from /Users/Sonna/.rbenv/versions/2.3.1/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require'
  from c.rb:2:in `<main>'

简单来说就是使用了Kernel's require method 它找不到 a.rb 文件,然后引发 LoadError 异常。

为了获取文件,您可以使用 Kernal's require_relative method

require_relative "a"
require_relative "b"

并且它将 ab 文件相对于 c 文件。

或者您可以将以下代码行添加到您的 c.rb 文件中,这是一个 Ruby Gems 中使用的通用约定来加载其自定义 scripts/libraries

current_directory = File.expand_path("../", __FILE__)
$LOAD_PATH.unshift(current_directory) unless $LOAD_PATH.include?(current_directory)

这将从当前文件 __FILE__ 添加当前目录 ../, 将其扩展为所述当前目录的绝对路径并将其添加到 现有的加载路径全局变量;例如

puts $LOAD_PATH
# => ["~/Projects/ruby/Whosebug_questions/the_scope_of_require",
#     "/usr/local/Cellar/rbenv/1.0.0/rbenv.d/exec/gem-rehash",
#     "~/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/did_you_mean-1.0.0/lib",
#     "~/.rbenv/versions/2.3.1/lib/ruby/site_ruby/2.3.0",
#     "~/.rbenv/versions/2.3.1/lib/ruby/site_ruby/2.3.0/x86_64-darwin15",
#     "~/.rbenv/versions/2.3.1/lib/ruby/site_ruby",
#     "~/.rbenv/versions/2.3.1/lib/ruby/vendor_ruby/2.3.0",
#     "~/.rbenv/versions/2.3.1/lib/ruby/vendor_ruby/2.3.0/x86_64-darwin15",
#     "~/.rbenv/versions/2.3.1/lib/ruby/vendor_ruby",
#     "~/.rbenv/versions/2.3.1/lib/ruby/2.3.0",
#     "~/.rbenv/versions/2.3.1/lib/ruby/2.3.0/x86_64-darwin15"]

require 内部使用按文件名查找,如果没有给出 绝对路径

If the filename does not resolve to an absolute path, it will be searched for in the directories listed in $LOAD_PATH ($:).

-- Kernel's require method

所以当我运行你再次编码时,我看到了以下内容

$ ruby c.rb
hello world

需要注意的是

A file will not be loaded again if its path already appears in $". For example, require 'a'; require './a' will not load a.rb again.

-- Module: Kernel (Ruby 2_4_0)

因此只要您的 require 方法之一在其中的方法之一之前出现一次 该文件被调用,它应该工作;所以你的两个例子都会起作用(如 只要将 sit 目录添加到 $LOAD_PATH 或者您使用 require_relative 代替)