【问题标题】:LoadError occurs when directly running Ruby source code in existing projects在现有项目中直接运行 Ruby 源代码时发生 LoadError
【发布时间】:2013-11-04 21:45:40
【问题描述】:

我是 Ruby/JRuby 的新手,当我尝试直接运行某些项目的 Ruby 源代码时,我被错误“LoadError: no such file to load”困扰了好几个星期。

我从 GitHub 下载了许多 Ruby 项目的源代码。是的,只有源代码,我没有安装它们,因为我的任务更多是分析代码本身。

举个例子,假设项目“rqrcode”具有以下(简化的)结构:

  • rqrcode
    • lib(文件夹)
      • rqrcode(文件夹)
        • core_ext(文件夹,里面有一些文件)
        • core_ext.rb
        • qrcode(文件夹,里面有一些文件)
        • qrcode.rb
      • rqrcode.rb
    • 测试(文件夹)
      • data.rb
      • test_rqrcode.rb

所以如果我在测试文件夹中运行“jruby test_rqrcode.rb”,它会在文件内的这一行抛出 LoadError:

require_relative "../lib/rqrcode"

这里还会抛出LoadError,lib文件夹下的rqrcode.rb文件:

require "rqrcode/core_ext"

错误信息是

LoadError: no such file to load -- rqrcode/core_ext
require at org/jruby/RubyKernel.java:1054
require at /Users/x5lai/.rvm/rubies/jruby-1.7.4/lib/ruby/shared/rubygems/custom_require.rb:36
(root) at /Users/x5lai/Downloads/rqrcode-master/lib/rqrcode.rb:12
require at org/jruby/RubyKernel.java:1054
(root) at /Users/x5lai/.rvm/rubies/jruby-1.7.4/lib/ruby/shared/rubygems/custom_require.rb:1
require at /Users/x5lai/.rvm/rubies/jruby-1.7.4/lib/ruby/shared/rubygems/custom_require.rb:36
(root) at test_rqrcode.rb:12

我真的不明白为什么它说找不到“rqrcode/core_ext”,因为那个文件夹确实存在!

这种错误并不总是发生。有时,当我下载其他与上述结构类似的 Ruby 项目的源代码时,它会成功运行所有“require”、“require_relative”语句。

我的朋友说这是一个 Ruby 默认加载路径问题。因此,我查看了我的 Ruby 加载路径中的内容。它充满了许多 Ruby 文件。但是,那些成功运行的 Ruby 项目在这些加载路径中也没有它们的 Ruby 文件(并且它们不使用“.unshift”来修改其代码中的加载路径)。所以我认为这不是那些失败项目的原因。

希望有人可以澄清我的疑问。也许是因为我的 JRuby 配置?我正在使用 Mac。我的 JRuby 版本是 1.7.4。

【问题讨论】:

  • 我发现 JRuby 将通过从当前项目根目录(在本例中为 /rqrcode )搜索来处理其 require 语句,而不管此 require 语句出现在项目中的什么位置。因此,lib/rqrcode.rb 中的require "rqrcode/core_ext" 会失败,因为 Jruby 在根文件夹 /rqrcode 中找不到 rqrcode 子文件夹。改正的方法有很多,比如把require语句改成require "lib/rqrcode/core_ext"或者在代码的require语句前加上$:.unshift(lib)

标签: ruby jruby load-path


【解决方案1】:

首先,ruby 加载路径不包括当前目录。
您可以通过在 cmd 中运行 jruby -e "$:" 来验证这一点。

其次,当您在test_rqrcode.rb 中执行require_relative "../lib/rqrcode" 时,您是在说“请在相对于我自己的路径中查找文件”。好的,马上就可以找到rqrcode.rb了。但是,rqrcode.rb 不知道在哪里可以找到自己需要的文件,所以它转到全局加载路径,即$:。由于$: 不包含lib 文件夹,因此在其lib 文件夹中找不到任何文件,因此返回异常。

知道了这一点,你应该在主脚本的加载路径中添加本地 lib 目录,这样后续的每个文件都将使用相同的加载路径环境。

$:.unshift "path_to_the_folder_need_to_include"

【讨论】:

  • 您在第二部分中是正确的,require_relative 确实适用于当前文件。我现在意识到 require "rqrcode/core_ext" 不起作用,因为 Ruby 将项目的根文件夹作为其加载路径,即虽然执行已从 test/test_rqrcode.rb 转移到 lib/rqrcode.rb,但 Ruby 仍然处理其 require 语句从根的角度。为什么说 Ruby 加载路径不包括当前目录?它适用于实际从项目根目录开始的require 语句。
  • 我的意思是,当Ruby在lib/rqrcode.rb中执行require "rqrcode/core_ext"这一行时,它会从项目的根文件夹中搜索rqrcode/core_ext,其中只包含libtest子文件夹.因此,它找不到require路径中指定的文件夹。
  • 不,require 将始终从加载路径查找路径。由于您使用的是默认加载路径,因此您的 PROJECT/rqrcode/lib/ 不在路径内,因此无法找到。
  • 对不起,我对 Jruby 不熟悉。 Jruby 实际上搜索此处指定的当前目录jruby.org/apidocs/org/jruby/runtime/load/LoadService.html
【解决方案2】:

在命令行上,您可以使用-I 开关将文件夹添加到$LOAD_PATH。例如:

ruby -I lib test/test_qrcode.rb

Ruby 项目通常会将其 lib 文件夹添加到其测试设置中的 $LOAD_PATH,通常是在名为 test_helper.rbspec_helper.rb 的文件中(取决于框架)。

【讨论】:

  • 由于我只处理项目的源代码,我不希望只为一个项目文件夹修改全局环境变量。我只是想确保源代码独立运行。
猜你喜欢
  • 1970-01-01
  • 2023-02-07
  • 1970-01-01
  • 2011-01-09
  • 1970-01-01
  • 2019-12-02
  • 2015-02-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多