Ruby: 'require' returns false 即使文件未加载

Ruby: 'require' returns false even though file not loaded

我有这个代码:

puts require './item'
puts $"

class Light < Item
  #code
end

Item class 在 item.rb:

require './v3d'
require './ray'

class Item
  attr_accessor :pos 

  def initialize(pos)
    @pos = pos
  end

  def check(pos, dir)
    return nil
  end

  def normal(ray)
    return nil
  end
end

当我 运行 我的程序打印此输出时:

false
enumerator.so
thread.rb
rational.so
complex.so
/usr/lib/x86_64-linux-gnu/ruby/2.3.0/enc/encdb.so
/usr/lib/x86_64-linux-gnu/ruby/2.3.0/enc/trans/transdb.so
/usr/lib/ruby/2.3.0/unicode_normalize.rb
/usr/lib/x86_64-linux-gnu/ruby/2.3.0/rbconfig.rb
/usr/lib/ruby/2.3.0/rubygems/compatibility.rb
/usr/lib/ruby/2.3.0/rubygems/defaults.rb
/usr/lib/ruby/2.3.0/rubygems/deprecate.rb
/usr/lib/ruby/2.3.0/rubygems/errors.rb
/usr/lib/ruby/2.3.0/rubygems/version.rb
/usr/lib/ruby/2.3.0/rubygems/requirement.rb
/usr/lib/ruby/2.3.0/rubygems/platform.rb
/usr/lib/ruby/2.3.0/rubygems/basic_specification.rb
/usr/lib/ruby/2.3.0/rubygems/stub_specification.rb
/usr/lib/ruby/2.3.0/rubygems/util/list.rb
/usr/lib/x86_64-linux-gnu/ruby/2.3.0/stringio.so
/usr/lib/ruby/2.3.0/rubygems/specification.rb
/usr/lib/ruby/2.3.0/rubygems/exceptions.rb
/usr/lib/ruby/vendor_ruby/rubygems/defaults/operating_system.rb
/usr/lib/ruby/2.3.0/rubygems/core_ext/kernel_gem.rb
/usr/lib/ruby/2.3.0/monitor.rb
/usr/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb
/usr/lib/ruby/2.3.0/rubygems.rb
/usr/lib/ruby/vendor_ruby/did_you_mean/version.rb
/usr/lib/ruby/vendor_ruby/did_you_mean/core_ext/name_error.rb
/usr/lib/ruby/vendor_ruby/did_you_mean/levenshtein.rb
/usr/lib/ruby/vendor_ruby/did_you_mean/jaro_winkler.rb
/usr/lib/ruby/vendor_ruby/did_you_mean/spell_checkable.rb
/usr/lib/ruby/2.3.0/delegate.rb
/usr/lib/ruby/vendor_ruby/did_you_mean/spell_checkers/name_error_checkers/class_name_checker.rb
/usr/lib/ruby/vendor_ruby/did_you_mean/spell_checkers/name_error_checkers/variable_name_checker.rb
/usr/lib/ruby/vendor_ruby/did_you_mean/spell_checkers/name_error_checkers.rb
/usr/lib/ruby/vendor_ruby/did_you_mean/spell_checkers/method_name_checker.rb
/usr/lib/ruby/vendor_ruby/did_you_mean/spell_checkers/null_checker.rb
/usr/lib/ruby/vendor_ruby/did_you_mean/formatter.rb
/usr/lib/ruby/vendor_ruby/did_you_mean.rb
/home/<user>/Documents/ruby/ray/write_ppm.rb
/home/<user>/Documents/ruby/ray/v3d.rb
/home/<user>/Documents/ruby/ray/pixel.rb
/home/<user>/Documents/ruby/ray/image.rb
/home/<user>/Documents/ruby/ray/material.rb

然后抛出:

/home/<user>/Documents/ruby/ray/light.rb:4:in `<top (required)>': uninitialized constant Item (NameError)

当调用 require './item' 时,没有错误并且 returns 错误。根据我对 require 工作原理的理解,程序似乎错误地认为它不需要加载 item.rb。为什么会发生这种情况,我该如何解决?

编辑:扩展了一些代码

我想您可能需要 require_relative

http://ruby-doc.org/core-2.4.0/Kernel.html#method-i-require_relative

对比

http://ruby-doc.org/core-2.4.0/Kernel.html#method-i-require

您说得对,如果 require 'my_lib' returns 为假,则 'my_lib' 已经加载。但是,这与定义 MyLib class 不同。您的 item.rb 是否定义了 Item class?

此外,Item 可能是在命名空间层次结构中的其他位置定义的。例如如果您的 item.rb 在 some_gem/item.rb 中,并且您从 some_gem/ 调用 require,它将加载成功,但 class 的名称可能是 SomeGem::Item。在这种情况下,您将无法直接从根命名空间访问它。

我能想到的最后一件事是 item.rb 文件正在更改,或者有一些非常动态的部分使解释器感到困惑。

在认为 require 不知何故搞砸之前,我认为问题是其中之一。

我通过为每个文件完全重写我的 require 语句解决了这个问题。我认为问题是:

  • item.rb 包含 require './ray'
  • ray.rb 包含 require './light'
  • light.rb 包含 require './item'class Light < Item

在加载 item.rb 时,解释器发现它还需要加载 ray.rb,因此 light.rb。当它到达 light.rb 内的 require './item' 时,它返回 false,因为它正在加载该文件。但是,由于它还没有完成加载,所以它没有出现在 $" 中。然后解释器需要访问 Item class 的定义来完成加载 light.rb,但是因为它需要完成加载 light.rb 才能加载 item.rb,所以翻译 NameError.

作为一个笼统的回答,与op无关,但因为我遇到了类似的问题,被搜索引擎指出了这里。

基本上 require 'http' 返回 false 而 gem 未加载。

我发现加载路径中有一个 http.rb 文件,并且正在加载它而不是标准的 gem。因此,仔细检查库加载路径下的 ruby 文件和 gem 名称没有冲突的文件名。