0

I have create a Ruby class Worker, file name is Worker.rb:

class Worker
 def initialize
  ...
 end

 def doTask(task_name)
  ...
 end
end

Then, I created another Ruby script file, named run.rb (it requires Worker):

require 'Worker'

worker = Worker.new
worker.doTask("sort")

Both two ruby files are located directly under the project folder:

ProjectFolder/
      -- Worker.rb
      -- run.rb

I run the run.rb under project folder by command:

ruby run.rb

But get following error:

/Users/John/.rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require': cannot load such file -- Worker (LoadError)
    from /Users/John/.rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require'
    from runme.rb:1:in `<main>'

Why?

Leem.fin
  • 40,781
  • 83
  • 202
  • 354

3 Answers3

2

I figured out after checking @Geo 's github project, I should use:

require_relative "worker"
Leem.fin
  • 40,781
  • 83
  • 202
  • 354
0

require looks for the required file from the so called load path and not the current directory. Since the syntax for looking in the current directory was awkward Ruby 1.9 introduces require_relative, which looks in the current directory.

Change your code like this:

require_relative "Worker"

instead of

require "Worker"
Boris Stitnicky
  • 12,444
  • 5
  • 57
  • 74
Geo
  • 93,257
  • 117
  • 344
  • 520
  • Could you please explain a bit, why? – Leem.fin Sep 03 '16 at 14:32
  • And I get the same error... – Leem.fin Sep 03 '16 at 14:33
  • Have a look at this for example: http://stackoverflow.com/questions/3672586/what-is-the-difference-between-require-relative-and-require-in-ruby – Geo Sep 03 '16 at 14:42
  • You can also have a look at a very simple full ruby project of mine which uses `require_relative` in a lot of places. https://github.com/mschwaig/event_deduplication_demo – mschwaig Sep 03 '16 at 14:53
  • 1
    Also, just to follow popular Ruby naming conventions, one should not call Ruby class files starting with a capital letter, e.g. 'worker.rb' instead of 'Worker.rb' – Paweł Duda Sep 03 '16 at 14:59
  • I checked your github ruby project, why you use `require_relative 'StatisticsUtils'` in `StatisticsUtil_demo.rb` without `./`, but in your answer, you said I should use `require_relative "./Worker"` ? We have the same structure, ruby files are located in the same folder. And I tried also `require_relative 'Worker'`, same error as well. – Leem.fin Sep 03 '16 at 15:19
  • 1
    Aha, I see the problem, my class name is `Worker` with captial `W` but the file name is `worker.rb` with smaller `w`, it works for me with `require_relative "worker"`. But anyhow, I don't understand why you ask me to add "./" in the `require`. – Leem.fin Sep 03 '16 at 15:23
  • I didn't post this answer, but I linked to my repo. I didn't know about the naming convention that @PawełDuda pointed out. – mschwaig Sep 03 '16 at 16:04
-1

The reason this does not work is because the current directory is not part of ruby's default load path.

If you run the following command, you will see what the current load path is and it will confirm that the current directory is not part of that path.

ruby -e 'puts $LOAD_PATH'

This should answer your primary question as to why the required file was not loaded.

As for a solution, require_relative will work and is probably the best solution in this case.

There are however still cases were inserting directories into the load path is helpful, if not required. For example say you have a script that can be run anywhere in the file system and you want the flexibility to require a particular version of your co-worker's foo class.

/afs/some_cell/u/john/some_ruby_lib
  prod/
    foo.rb
    bar.rb
 prev/
    foo.rb
    bar.rb
 beta/
    foo.rb
    bar.rb

In a case like this either setting the RUBYSIM var (maybe in a wrapper) or setting the proper include path on the ruby command line can be a useful solution.

Again, your co-worker has not published this as a gem, he is just providing a shared directory.

There are several ways you can insert directories into the load path when it is appropriate, as demonstrated below:

You can use the -I command line flag

ruby -I some_path -e 'puts $LOAD_PATH'

You can set the RUBYLIB env var to include your current directory.

on unix/linix/osx

export RUBYLIB=some_path

on windows

set RUBYLIB=some_path

nPn
  • 16,254
  • 9
  • 35
  • 58
  • When I have the dot `.` between `-I` and `run.rb`, I get the same error, when I remove the dot, it just hanging there, how can I get more debug information, which flag should I add in the command? – Leem.fin Sep 03 '16 at 15:04
  • man ruby or ruby -h should give you more info on the ruby command – nPn Sep 03 '16 at 15:10
  • Anyhow, when I run `ruby -I run.rb` , it is hanging there. Even I added a simple code `puts 'helloworld'` as the first line of run.rb , I don't see it, it just hang there. – Leem.fin Sep 03 '16 at 15:14
  • you need to give it a path after the -I ruby -I . run.rb you can try -I. -I./ also, btw, what operating system are you using? – nPn Sep 03 '16 at 15:20
  • This is way too complicated, I found a simple solution already. – Leem.fin Sep 03 '16 at 15:25
  • It's not really complicated at all. ruby uses a search path to locate files in require statements. If the location you want to put the files in is not part of that search path you can add the location to the search path by either including it on the command line via ruby -Ipath or setting up the RUBYLIB environment variable to include the path you want. – nPn Sep 03 '16 at 15:29
  • Thanks, good to know, but for my case, I think relative path is more suitable for 'require' statement, other developers can just clone my code and run it instead of having to include the path to Ruby search path. – Leem.fin Sep 03 '16 at 15:36
  • This is terrible, terrible advice. Manually fiddling with `$LOAD_PATH` hasn't been needed since 2007 outside of exceptional circumstances. If you want to load a file relative to the current file, use `require_relative`. Otherwise, your package manager (e.g. Bundler, RubyGems, APT/dpkg, YUM/RPM, …) should have set up the `$LOAD_PATH` for you. – Jörg W Mittag Sep 03 '16 at 16:54
  • This answer attempted to answer the primary question, which was __why__ his required file was not found by showing that the current directory is not part of the standard ruby search path and a couple of ways the search path could be manipulated. I agree that in simple cases like this require_relative is the way to go, but there are still valid uses for inserting paths into the load path. I will update my answer. – nPn Sep 03 '16 at 17:36
  • updated my answer, if some one still finds it usefulness please provide feedback. – nPn Sep 03 '16 at 18:23