0

I'm new to Ruby/JRuby and has been disturbed by the error "LoadError: no such file to load" for many weeks, when I try to directly run the Ruby source code of certain projects.

I downloaded the source code of many Ruby projects from GitHub. Yes only the source code, I didn't install them because my task is more on analyzing the code itself.

Let's take an example, say the project "rqrcode" has the following (simplified) structure:

  • rqrcode
    • lib (folder)
      • rqrcode (folder)
        • core_ext (folder, with some files inside)
        • core_ext.rb
        • qrcode (folder, with some files inside)
        • qrcode.rb
      • rqrcode.rb
    • test (folder)
      • data.rb
      • test_rqrcode.rb

So if I run "jruby test_rqrcode.rb" inside the test folder, it throws LoadError at this line inside the file:

require_relative "../lib/rqrcode"

And it also throws LoadError at here, the rqrcode.rb file in lib folder:

require "rqrcode/core_ext"

The error message is

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

I really don't understand why it says it cannot find "rqrcode/core_ext" because that folder does exist there!

Such error doesn't always occur. Sometimes, when I download the source code of other Ruby projects which have similar structure as above, it runs successfully with all the "require", "require_relative" statements.

My friend says it is a Ruby default load path problem. I therefore went to look at what's inside my Ruby load path. It's full of many Ruby files. But, those Ruby projects that run successfully do not have their Ruby files in these load path as well (and they do not use ".unshift" to modify their load path inside their code). So I don't think this is the cause of those failing projects.

Hope there's someone who could clarify my doubts. Maybe it's because of my JRuby configuration? I'm using a Mac. My JRuby version is 1.7.4.

Renato Zannon
  • 28,805
  • 6
  • 38
  • 42
Erencie
  • 391
  • 2
  • 3
  • 12
  • I have found that JRuby would process its `require` statement by searching from the current project root directory (in this case, /rqrcode ), regardless of where this `require` statement appears inside the project. Therefore, `require "rqrcode/core_ext"` in lib/rqrcode.rb would fails because Jruby cannot find rqrcode subfolder in the root folder /rqrcode. There are many ways to correct it, such as changing require statement to `require "lib/rqrcode/core_ext"` or by adding `$:.unshift(lib)` before the require statement in the code. – Erencie Nov 05 '13 at 04:40

2 Answers2

1

Firstly, ruby load path doesn't include current directory.
You can verify this by running jruby -e "$:" in cmd.

Secondly, when you do require_relative "../lib/rqrcode" in test_rqrcode.rb, you are saying "please find the file at a path relative to myself". Okay, it can find rqrcode.rb right away. However, rqrcode.rb doesn't know where to find its own required files, so it goes to global load path, which is the $:. Since $: doesn't include the lib folder, it cannot find any file residing inside its lib folder, thus return a exception.

Knowing this, you should add local lib directory to the load path in your main script, so every subsequent file will use the same load path environment.

$:.unshift "path_to_the_folder_need_to_include"

coderek
  • 1,860
  • 14
  • 20
  • You're correct in the second part that `require_relative` does work from the current file. And I now realize that `require "rqrcode/core_ext"` isn't working because Ruby goes to the root folder of the project as its load path, i.e. although the execution has shifted from `test/test_rqrcode.rb` to `lib/rqrcode.rb`, Ruby still process its `require` statement from the root perspective. And why do you say Ruby load path doesn't include current directory? It works for `require` statement that starts from the root directory of the project actually. – Erencie Nov 05 '13 at 03:37
  • I mean, when Ruby executes this line `require "rqrcode/core_ext"` in `lib/rqrcode.rb`, it will search for `rqrcode/core_ext` from the root folder of the project, which contains only `lib` and `test` subfolders. Therefore, it can't find the folder specified in the require path. – Erencie Nov 05 '13 at 03:52
  • Nope, `require` will always look up the path from load path. since you are using default load path, your `PROJECT/rqrcode/lib/` is not inside the path, so it cannot find. – coderek Nov 05 '13 at 03:58
  • 1
    Sorry I am not familiar about Jruby. Jruby in fact searches current directory as specified here http://jruby.org/apidocs/org/jruby/runtime/load/LoadService.html – coderek Nov 05 '13 at 04:30
0

On the command line, you can add a folder to the $LOAD_PATH by using the -I switch. For example:

ruby -I lib test/test_qrcode.rb

It is common for ruby projects to add their lib folder to the $LOAD_PATH on their test setup, typically on a file called test_helper.rb or spec_helper.rb (depending on the framework).

Renato Zannon
  • 28,805
  • 6
  • 38
  • 42
  • Since I'm going to deal with the source code of the projects only, I prefer not to modify the global environment variable just for one project folder. I just want to make sure that the source code runs by itself standalone. – Erencie Nov 05 '13 at 03:45