2

Going through "Well Grounded Rubyist" book and some code examples have you use require to load files. Unfortunately when using require "stacklike" I get this error "/home/userP/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems/core_ext/kernel_require.rb:55:in 'require': cannot load such file -- stacklike (LoadError)"

Using require_relative "stacklike" works just fine. Why does this work, but not require?

Ordep81
  • 967
  • 4
  • 13
  • 18
  • Possible this should solve your issue [difference between require and require_relative](http://stackoverflow.com/a/29865560/1087841) – Saad Jun 21 '16 at 06:37
  • 1
    use `require './stacklike'` – Sergio Tulentsev Jun 21 '16 at 06:41
  • `require "./stacklike"` worked! Trying to understand why `require "stacklike"` doesnt. – Ordep81 Jun 21 '16 at 06:57
  • 3
    Do not *ever* use `require './stacklike'`. It will look up the file in the current working directory, which is outside your script's control, and thus you cannot guarantee which file will get loaded. If an attacker can trick you into changing into a directory under their control, they can inject their own arbitrary code into a script running with your user account and permissions! – Jörg W Mittag Jun 21 '16 at 07:21

2 Answers2

2

It is because require is relative to the working directory (and library search path) and "stacklike.rb" is in the same directory as the file you are requiring it from and not in your working directory.

You can either move stacklike.rb to your working directory - or even better continue using require_relative - there is nothing wrong with it. It is even better - since when you read the file you know exactly where it should be.

Senad Uka
  • 1,131
  • 7
  • 18
  • So if "stacklike.rb" and "stack.rb"(file doing the require) are in the same directory, say '/ruby_examples' what would be my actual working directory then? – Ordep81 Jun 21 '16 at 06:52
  • Working directory is where you run your app from. Or it can be set by environment variables from UI. So which directory are you in when you are running the app ? And how are you running it ? – Senad Uka Jun 21 '16 at 06:57
  • It's whatever directory you were in when you ran the script. E.g. if your script is in `/home/ordek/myproject/bin/myscript.rb` and you are in `/home/ordek/myproject` and call it like `ruby bin/myscript.rb`, then the current working directory is `/home/ordek/myproject`. If you are in `/home/ordek/myproject/bin` and call it like `./myscript.rb`, then your current working directory is `/home/ordek/myproject/bin`. – Jörg W Mittag Jun 21 '16 at 07:01
  • The directory that im in when i run it is `~/Documents/rubyprojects/bookexample` and I run it using `ruby stack.rb` – Ordep81 Jun 21 '16 at 07:17
2

require searches for the file to load in the $LOAD_PATH. require_relative searches for the file relative to the directory where the file resides that the call to require_relative is in. The two are completely different.

require './stacklike' will look for the file in the current working directory. This is a really bad idea: if your script is in /home/ordek/myproject/bin/myscript.rb and you are in /home/ordek/myproject and call it like ruby bin/myscript.rb, then the current working directory is /home/ordek/myproject and require './stacklike' will look for a file /home/ordek/myproject/stacklike.rb. If you are in /home/ordek/myproject/bin and call it like ./myscript.rb, then your current working directory is /home/ordek/myproject/bin and require './stacklike' will look for a file /home/ordek/myproject/bin/stacklike.rb.

In other words: which file gets loaded depends on circumstances outside the control of your script (after all, your script cannot influence from where it is called), which is not good (to say the least). In fact, it can allow an attacker to inject own code into your script, which can be disastrous.

For that reason, you should never rely on the current working directory when loading files.

For your situation, require_relative is the only correct choice.

Jörg W Mittag
  • 363,080
  • 75
  • 446
  • 653
  • When would it be correct or safe to use `require` over `require_relative`? – Ordep81 Jun 21 '16 at 07:31
  • 1
    When you want to load something from the `$LOAD_PATH`. Like I said, the two do different things, there really isn't much of a choice: if you want to load something relative to the currently executing file, your only option is `require_relative`, when you want to load something from the `$LOAD_PATH`, your only option is `require`. The only overlap is that both can be used for loading something from the current working directory, which however is a bad idea and shouldn't be done anyway. – Jörg W Mittag Jun 21 '16 at 07:33